さくらのクラウドでUbuntuのクラウドイメージ+cloud-initを利用する

はじめに

さくらのクラウド上でUbuntuの「クラウドイメージ」を利用する機会がありましたので方法をまとめておきます。

手順

順番にみていきます。

Ubuntuクラウドイメージの準備

cloud-initが構築済みの「クラウドイメージ」というものがUbuntuで提供されています。

gihyo.jp

今回はこれを利用します。ただし、さくらのクラウドはraw形式にのみ対応していますので、イメージをダウンロードした後変換してからさくらのクラウドへアップロードします。

なお、以下の手順では作業マシン上でqemu-imgコマンドとusacloudコマンドを利用します。

qemu-imgコマンドについてはyum install qemu-imgapt install qemu-utilsなどでインストールしておきます。
usacloudコマンドはこちらを参考にインストール&APIキーの設定を済ませておきます。

# ダウンロード(今回は18.04を利用)
curl -sL -o ubuntu.img https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img 

# qcowからraw形式(sparse)へ変換
qemu-img convert ubuntu.img ubuntu-sparse.raw

# non-sparseファイルにする
cp --sparse=never ubuntu-sparse.raw ubuntu.raw

# さくらのクラウド上にアーカイブとしてアップロード
usacloud archive create --name my-ubuntu --size 20 --archive-file ubuntu.raw  

qemu-imgでraw形式に変換後、non-sparseファイルにするのがポイントです。
(試しにsparseファイルのまま試したらサーバ起動できませんでした)

NoCloudデータソース用にISOイメージを作成&アップロード

次にNoCloudデータソース用のISOイメージを作成、アップロードを行います。 NoCloudデータソースについては以下の記事を参考に作成しました。 gihyo.jp

今回はubuntuユーザーにパスワードを設定しパスワード認証でSSH接続できるようにするという内容になってます。

# user-dataファイルの作成(!パスワードは任意の値に置き換えてください)
PASSWORD=your-password
cat >user-data <<EOF
#cloud-config
password: $PASSWORD
chpasswd: { expire: False }
ssh_pwauth: True
EOF

# meta-dataファイルの作成(とりあえず空でOK)
touch meta-data

# ISOイメージの作成(linux上で作業する場合)
mkisofs -R -V cidata -o cloud-init.iso ./

# ISOイメージの作成)mac上で作業する場合)
# hdiutil makehybrid -iso -joliet -default-volume-name cidata -o cloud-init.iso ./

# さくらのクラウド上にISOファイルをアップロード
usacloud iso-image create --name cloud-init --iso-file cloud-init.iso

作成したアーカイブ/ISOイメージを利用してサーバ作成

次にサーバの作成を行います。

usacloud server build \
  --source-archive-id=`usacloud archive read -q my-ubuntu` \
  --iso-image-id=`usacloud iso-image read -q cloud-init` \
  --name=example

この後作成したサーバに対しSSH接続できるようになっているはずです。

まとめ

  • Ubuntuクラウドイメージをダウンロード後、non-sparseなraw形式に変換してアップロード
  • cloud-initのデータソースにはISOイメージファイルを作成してNoCloudデータソースを利用

ISOイメージファイルの作成部分をうまく自動化すれば色々活用できますね。

以上です。

GitHub ActionsでTerraformを実行する時にTerraform Cloudをバックエンドに指定する

某所で「GitHub ActionsからTerraform Cloudを使おうとしたが上手くいかなかった」という投稿を拝見しました。
うまいこと設定すればちゃんと動かせますのでその方法などについてまとめておきます。

TL; DR

  • Terraform CloudでのExecution ModeはデフォルトでRemoteになってる
  • クレデンシャルをGitHub側のSecretから環境変数として渡す場合はExecution ModeLocalに変更する

最初に: やりたいこと

このために、リポジトリ上でGitHub Actionsの設定を行い、リポジトリにtfファイルをコミット、PullRequestの作成を行います。

利用するtfファイル

# バックエンドの設定
terraform {
  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "your-organization-name"

    workspaces {
      name = "your-workspace-name"
    }
  }
}

# プロバイダー
provider "google" {
  project = "your-project-name"
  region  = "us-west1"
}

# リソースの例
data "google_project" "project" {}

output "project_number" {
  value = "${data.google_project.project.number}"
}

この例はGCPプロバイダーを使うようにしています。

Terraform CloudとGCPプロバイダーのクレデンシャルについてはGitHub ActionsのSecretに保存しておいて環境変数(TF_ACTION_TFE_TOKENGOOGLE_CREDENTIALS)に指定します。

ワークフローファイルの定義

GitHub Actionsのワークフローファイルは以下を利用します。

参考: https://www.terraform.io/docs/github-actions/getting-started/index.html

on:
  pull_request:
    types: 
      - opened
      - synchronize
      - closed
    branches:
      - master
name: Terraform
jobs:
  terraform-fmt:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1.0.0

    - name: terraform-fmt
      uses: hashicorp/terraform-github-actions/fmt@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        # env
        TF_ACTION_WORKING_DIR: "."

  terraform-init:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1.0.0

    - name: terraform-init
      uses: hashicorp/terraform-github-actions/init@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

  terraform-validate:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1.0.0

    - name: terraform-init
      uses: hashicorp/terraform-github-actions/init@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

    - name: terraform-validate
      uses: hashicorp/terraform-github-actions/validate@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

  terraform-plan:
    needs:
    - terraform-fmt
    - terraform-init
    - terraform-validate
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1.0.0

    - name: terraform-init
      uses: hashicorp/terraform-github-actions/init@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

    - name: terraform-plan
      uses: hashicorp/terraform-github-actions/plan@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

  terraform-apply:
    needs:
    - terraform-plan
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1.0.0

    - name: terraform-init
      if: github.event.pull_request.merged == true
      uses: hashicorp/terraform-github-actions/init@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

    - name: terraform-apply
      if: github.event.pull_request.merged == true
      uses: hashicorp/terraform-github-actions/apply@v0.4.4
      env:
        # secrets
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
        TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
        # env
        TF_ACTION_WORKING_DIR: "."

Secretに忘れずにTerraform CloudとGCPプロバイダーのクレデンシャルを登録しておいてください。

これでPR時にinit,fmt,validate,planが実行され、マージしたらapplyも実行されます。

クレデンシャルが見つからないエラーとなる

このままこのアクションを動かすとplan実行時に以下のようなエラーが出ます。

Error: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

  on terraform.tf line 14, in provider "google":
  14: provider "google" ***

原因

tfファイルなどでTerraform Cloudをバックエンドとして指定する際、指定したワークスペースが存在しない場合は新たに作成されます。
そして、新規作成されたワークスペースの場合、Remote Operationsがデフォルトで有効となっています。

Remote Operationsとは、Terraform CLIからplanapplyを実行することで実際の処理をリモートのインフラ上で行える仕組みで、現在はTerraform Cloudでのみサポートされています。

www.terraform.io

Remote Operationsでは環境変数はTerraform Cloudのワークスペース上で定義されたものが利用されます。
なのでGitHub ActionsのSecretを設定、環境変数に指定してもそれが利用されず、クレデンシャルが見つからないというエラーとなります。

対応

ワークスペースの設定でExecution Modeという項目があります。
これはRemote Operationsの有効/無効を切り替えられるもので、この項目をLocalに設定することでplanapplyはローカル(GitHub Actions上)で実行され、tfstateはTerraform Cloudに保存されるようになります。

f:id:febc_yamamoto:20191010204044p:plain

まとめ

以下2点を押さえておきましょう。

  • Terraform CloudでのExecution ModeはデフォルトでRemoteになってる
  • クレデンシャルをGitHub側のSecretから環境変数として渡す場合はExecution ModeLocalに変更する

あと、パブリックなリポジトリGitHub Actionsを使ってapplyを実行するのは推奨されていない*1のでこの辺も理解した上で利用しましょう。

以上です。

さくらのクラウド対応版Terraformerがv0.8系になりました

先月リリースしたさくらのクラウド対応版Terraformerが本家のバージョンアップに追随してv0.8系になりました。

sacloud/v0.8.1のリリースページ:

github.com

以前のsacloud/terraformerについての記事:

febc-yamamoto.hatenablog.jp

sacloud/terraformer v0.8系での主な変更点

  • Terraform v0.12系対応
  • 不要な依存関係の出力を抑制

Terraform v0.12対応

これまではTerraform v0.11系のみ対応でv0.12系だと色々とエラーが出ていましたが、このバージョンからv0.12系に対応しました。

ただしv0.11系には非対応となりましたので、もしv0.11系を使いたい場合はterraformer v0.7系を利用する必要があります。

不要な依存関係の出力を抑制

v0.7系では依存関係のあるリソースへの参照が不要な場合でも出力されていました。

terraformer import sakuracloud --resource=serverと指定した場合の出力例:

# 不要なdataブロックの出力が行われてしまう

data "terraform_remote_state" "cdrom" {
  backend = "local"

  config {
    path = "../../../generated/sakuracloud/cdrom/terraform.tfstate"
  }
}

data "terraform_remote_state" "disk" {
  backend = "local"

  config {
    path = "../../../generated/sakuracloud/disk/terraform.tfstate"
  }
}

data "terraform_remote_state" "icon" {
  backend = "local"

  config {
    path = "../../../generated/sakuracloud/icon/terraform.tfstate"
  }
}

# ...

これがv0.8系ではきちんと出力を抑制してくれます。
(もちろん--resource=server,icon)などとした場合は出力してくれます。

これでかなり使い勝手がよくなったと思います。

ぜひご利用ください!

以上です。

cert-managerでさくらのクラウドDNSを使ってワイルドカード証明書を発行する

cert-managerのさくらのクラウド対応版

Kubernetes上で証明書の発行/更新の自動化を行えるcert-managerをフォークしてさくらのクラウド対応版をリリースしました。

github.com

これを利用することでさくらのクラウドDNSを利用して証明書の発行/更新が行えるようになります。

今回はこのさくらのクラウド対応版cert-managerを利用して証明書を発行する方法をご紹介します。

なお今回は現時点(2019/10/3)の最新版のv0.11.0-alpha.0を利用します。
v0.11系はまだalpha版となっており、今後細かな仕様変更などがあるかもしれない点には留意ください。

発行までの手順

以下のような流れとなります。

準備しておくもの

最後のさくらのクラウドDNSヘのゾーン登録ですが、証明書を発行したいドメインさくらのクラウドDNSへあらかじめ登録しておくということです。
(レコードは登録しておかなくても構いません)

ゾーン登録後に表示されるDNSサーバに対して権限移譲を行うところまでは済ませておいてください。

manual.sakura.ad.jp

さくらのクラウド対応版cert-managerのインストール

Helm Chartを用意していますのでこちらを利用してインストールします。

helm init

まずはhelm initしておきます。
(以下はRBACが有効なクラスタhelm initする場合の例です。)

kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
helm init --service-account tiller

helm lsなどを実行してエラーが出ないことを確認しておきます。

もしError: could not find a ready tiller podが表示されたら少し待ちましょう。

cert-managerのインストール

まずCRDの作成とNameSpaceの作成を行い、その後helm installを実行します。

# CRDの登録
kubectl apply -f https://raw.githubusercontent.com/sacloud/cert-manager/sacloud/v0.11.0-alpha.0/deploy/manifests/00-crds.yaml

# NameSpaceの作成
kubectl apply -f https://raw.githubusercontent.com/sacloud/cert-manager/sacloud/v0.11.0-alpha.0/deploy/manifests/01-namespace.yaml

# sacloudリポジトリの追加
helm repo add sacloud https://sacloud.github.io/helm-charts/

# cert-managerのインストール
helm install --name cert-manager --namespace cert-manager --version v0.11.0-alpha.0 sacloud/cert-manager

これでcert-managerのインストールができました。

さくらのクラウドAPIキーをSecretに格納

次にcert-managerからさくらのクラウドDNSAPIを通じて操作する際に利用するAPIキーをSecretとして作成します。

まず以下のようなyamlファイルを作成します。 (ここではsecret.yamlというファイル名にしました)

apiVersion: v1
kind: Secret
metadata:
  name: sakuracloud-dns
  namespace: cert-manager
type: Opaque
data:
  access-token: <BASE64エンコードしたAPIトークン>
  access-secret: <BASE64エンコードしたAPIシークレット>

APIキーのトークン/シークレットはBASE64エンコードした値に置き換えてください。
(BASE64エンコードecho '<APIトークン>' | base64などのコマンドでOK)

その後kubectlで登録します。

kubectl apply -f secret.yaml

今回は後ほどClusterIssuerを利用するつもりですのでSecretのNameSpaceをcert-managerにしています。
ClusterIssuerではなくIssuerを利用する場合は適宜修正してください。

参考: https://docs.cert-manager.io/en/release-0.11/reference/clusterissuers.html

Issuer or ClusterIssuerの作成

次にIssuer、またはClusterIssuerを作成します。

参考: - https://docs.cert-manager.io/en/release-0.11/reference/issuers.html - https://docs.cert-manager.io/en/release-0.11/reference/clusterissuers.html

今回はClusterIssuerを作成します。

まず以下のようなyamlファイルを作成します。 (今回はissuer.yamlというファイル名にしました)

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: example-issuer
spec:
  acme:
    email: <メールアドレス>
    # ステージング
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # 本番
    #server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: example-issuer-account-key
    solvers:
      - dns01:
          sakuracloud:
            accessTokenSecretRef:
              name: sakuracloud-dns
              key: access-token
            accessSecretSecretRef:
              name: sakuracloud-dns
              key: access-secret

メールアドレスの部分は適宜修正してください。

その後kubectlで登録します。

kubectl apply -f issuer.yaml

これで証明書の発行を行う準備が整いました。続いて早速証明書の発行を行います。

Certificateリソースを作成して証明書を発行

以下のようなyamlファイルを作成します。
(今回はcert.yamlというファイル名にしました)

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
 name: example-tls
 namespace: default
spec:
  secretName: example-tls
  commonName: '*.<ゾーン名>'
  dnsNames:
    - '*.<ゾーン名>'
  issuerRef:
    name: example-issuer
    kind: ClusterIssuer    

ゾーン名の部分は各自で適切に置き換えてください。
例えばexample.comというゾーン名に対し*.hoge.example.comというワイルドカード証明書を発行する場合、spec.commonNamespec.dnsNames[*]には*.hoge.example.comを指定します。

あとはkubectlで登録するだけです。

kubectl apply -f cert.yaml

確認

取得できているか確認してみます。

$ kubectl describe cert example-tls

Name:         example-tls
Namespace:    default
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"cert-manager.io/v1alpha2","kind":"Certificate","metadata":{"annotations":{},"name":"example-tls","namespace":"default"},"sp...
API Version:  cert-manager.io/v1alpha2
Kind:         Certificate
Metadata:
  Creation Timestamp:  2019-10-03T06:26:57Z
  Generation:          5
  Resource Version:    2951
  Self Link:           /apis/cert-manager.io/v1alpha2/namespaces/default/certificates/example-tls
  UID:                 ccde4ca9-e5a6-11e9-a60d-9ca3ba2833af
Spec:
  Common Name:  *.example.com
  Dns Names:
    *.example.com
  Issuer Ref:
    Kind:       ClusterIssuer
    Name:       example-issuer
  Secret Name:  example-tls
Status:
  Conditions:
    Last Transition Time:  2019-10-03T06:29:12Z
    Message:               Certificate is up to date and has not expired
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2020-01-01T05:29:11Z
Events:
  Type    Reason        Age    From          Message
  ----    ------        ----   ----          -------
  Normal  GeneratedKey  2m44s  cert-manager  Generated a new private key
  Normal  Requested     2m43s  cert-manager  Created new CertificateRequest resource "example-tls-2800673269"
  Normal  Issued        29s    cert-manager  Certificate issued successfully

Eventsの部分にIssuedが表示されたら発行完了してます。

発行された証明書を確認してみます。

$ kubectl get secret 

apiVersion: v1
data:
  ca.crt: null
  tls.crt: ...
  tls.key: ...
kind: Secret
metadata:
  annotations:
    cert-manager.io/alt-names: '*.example.com'
    cert-manager.io/certificate-name: example-tls
    cert-manager.io/common-name: '*.example.com'
    cert-manager.io/ip-sans: ""
    cert-manager.io/issuer-kind: ClusterIssuer
    cert-manager.io/issuer-name: example-issuer
  creationTimestamp: "2019-10-03T06:26:57Z"
  name: example-tls
  namespace: default
  resourceVersion: "2949"
  selfLink: /api/v1/namespaces/default/secrets/example-tls
  uid: cd15196e-e5a6-11e9-a60d-9ca3ba2833af
type: kubernetes.io/tls

data.tls配下にBASE64エンコードされた証明書データが格納されているはずです。

これでワイルドカード証明書を発行することができました。

さくらのクラウド対応版cert-managerの利用上の注意

さくらのクラウド対応版のcert-managerはオリジナルのcert-manager v0.11系以降のみに対応予定です。
それ以前のバージョンには対応しませんのでご注意ください。

終わりに

さくらのクラウド対応版cert-managerを利用することで、さくらのクラウドDNSを用いてワイルドカード証明書の発行が行えます。
さくらのクラウド上でKubernetesを利用する場合などに便利だと思います。 ぜひご利用ください。

以上です。

Terraformerで既存のさくらのクラウド環境からリバースTerraformする

UPDATE: 2022-06 コメントでご指摘いただいたtypoを修正(from: resource= to resources=)

既に存在するリソースの情報からTerraformのコード(tfファイル + tfstateファイル)を生成できるterraformerというツールがあります。

github.com

このTerraformerをフォークしてさくらのクラウド対応を行ったものをリリースしました。

github.com

これを使えばさくらのクラウド上に存在するサーバやディスクなどのリソースからTerraformのコードを生成できます。

Terraformerとは

Terraformerとは前述の通り既存のリソースからTerraformのコードを生成してくれるツールです。
様々なプラットフォームに対応しており、現時点での最新版(0.7.9)では以下のようなものに対応しています。

Terraformerの大まかな処理の流れは次の通りです。

  • 1) 対象プラットフォームのAPIを呼ぶなどして実リソースの情報を取得
  • 2) 取得したリソース毎にTerraformプロバイダーのRefresh(terraform refreshコマンド相当の処理)を実行
  • 3) 得られたtfstateの情報からtfファイルを生成

1)と3)がTerraformer側で実装されており、2)はgRPCなどでTerraformプロバイダーの実行ファイルを利用する形になっています。 また、1)は対象プラットフォーム毎にプロバイダーという仕組み(インターフェース)で拡張できるようになっており、さくらのクラウド対応はこれを実装して行いました。

さくらのクラウド対応版Terraformer

さくらのクラウド対応版Terraformerを利用するには

  • ローカルマシンにインストールする方法
  • Dockerを利用する方法(推奨)

の2つの方法があります。

ローカルマシンにインストールする場合

terraformerコマンドとTerraform/Terraformプロバイダーそれぞれの実行ファイルをローカルマシンにダウンロードしておく必要があります。

それぞれバージョンに注意してダウンロードしてください。

なおterraformerの次のバージョンからTerraform v0.12対応される見込みです。 それまではTerraform v0.11系を利用しておくのが無難です(使えないこともないがエラーが出る箇所がいくつかある)。

バージョンに気をつけてダウンロードするのはなかなか大変なので次のDockerを利用する方法が推奨です。

Dockerを利用する場合(推奨)

さくらのクラウド対応版terraformerとTerraform/TerraformプロバイダーをセットにしたDockerイメージを公開しています。

https://hub.docker.com/r/sacloud/terraformer

以下のように利用します。

$ docker run -it --rm -v $PWD:/work sacloud/terraformer

さくらのクラウドAPIキーの指定

APIキーはコマンドラインオプション、または環境変数で指定します。

コマンドラインオプションで指定する場合は--token/--secretAPIトークン/シークレットを指定します。

$ terraformer import sakuracloud --token=APIトークン --secret=APIシークレット --resources=server,disk,icon

環境変数の場合はSAKURACLOUD_ACCESS_TOKEN/SAKURACLOUD_ACCESS_TOKEN_SECRETを指定します。
(UsacloudやTerraformなどと同じ環境変数です)

$ export SAKURACLOUD_ACCESS_TOKEN=APIトークン
$ export SAKURACLOUD_ACCESS_TOKEN_SECRET=APIシークレット
$ terraformer import sakuracloud --resources=server,disk,icon

Dockerの場合は以下のような感じで指定します。

$ docker run -it --rm -v $PWD:/work -e SAKURACLOUD_ACCESS_TOKEN=APIトークン -e SAKURACLOUD_ACCESS_TOKEN_SECRET=APIシークレット sacloud/terraformer

使い方

基本的な使い方

対象となるリソースの種別を指定してterraformerコマンドを実行します。
例えばサーバを対象とする場合以下のように--resourcesオプション(または-r)を指定して実行します。

$ terraformer import sakuracloud --resources=server 

複数のリソース種別を対象にする場合は以下のように--resourcesオプションにカンマ区切りで指定します。

# サーバとディスクを対象にする場合
$ terraformer import sakuracloud --resources=server,disk

指定できるリソース種別はGitHubのREADME.mdを参照してください。

https://github.com/sacloud/terraformer#サポートしているリソース

またデフォルトではカレントディレクトリ配下にgenerated/sakuracloud/{リソース種別}/というディレクトリがリソース種別毎に作成され、その中にtfファイル/tfstateファイルが生成されます。(オプションで変更可能)

例として、シンプル監視を対象にコード生成した場合、以下のようなコードが生成されます。

# シンプル監視を対象にコード生成
$ terraformer import sakuracloud --resources=simpleMonitor

# 生成されたコードを確認
$ cat generated/sakuracloud/simpleMonitor/simple_monitor.tf
resource "sakuracloud_simple_monitor" "simpleMonitor-000-example" {
  description = "example"
  enabled     = true

  health_check {
    delay_loop     = "1800"
    host_header    = "example.usacloud.jp"
    path           = "/status"
    protocol       = "https"
    status         = "200"
  }

  notify_email_enabled = false
  notify_email_html    = false
  notify_slack_enabled = true
  notify_slack_webhook = "https://hooks.slack.com/services/xxx/xxxx/xxxx"
  target               = "example.usacloud.jp"
}

対象リソースを限定する場合

現在は対象リソースをIDで指定することでコード生成の対象リソースを限定できます。
--filterオプションにTerraformでのリソース種別+リソースのIDをコロン区切りで指定するようになっています。

# IDがid1,id2,id4のリソースのみを対象とする場合
$ terraformer import sakuracloud --resources=server --filter=sakuracloud_server=id1:id2:id4

利用上の注意

残念ながら一部の項目は入力専用となっており、Terraformerから生成できません。例えばサーバの管理者パスワードなどです。
このため、これらの項目については生成されたコードを手作業で修正する必要があります。

出力されない項目はこちらに一覧がありますのでこれを参考に修正してください。

https://github.com/sacloud/terraformer#サポートしない項目

これ以外にもいくつか注意事項がありますのでREADME.mdの利用上の注意を読んだ上でご利用ください。

https://github.com/sacloud/terraformer#利用上の注意

運用上の注意

前述の利用上の注意の通り、出力されない項目がいくつかある問題があるため、DNSレコードの管理やVPCルータの設定を管理するといったシンプルな用途以外は出力されたコードをそのまま実運用するのはなかなか難しいと思います。

出力されたコードは参考程度と割り切って利用するというのも手だと思います。 1からtfファイルを手作業で記載するよりは楽だと思いますのであくまでも道具の一つとしての利用がオススメです。

まとめ

既存のリソースからTerraformのコード生成を行えるTerraformerのさくらのクラウド対応版を紹介しました。
バージョンの縛りがあるためDockerから利用するのがオススメです。

また、いくつか出力されない項目があるなど利用上の注意点が結構あり、出力されたコードをそのまま実運用するというのは難しいです。
とはいえ1からtfファイルを書くより楽になると思いますので利用できる場面では便利にご利用いただけると思います。

ぜひ使ってみてください!

以上です。

Pulumi+さくらのクラウドでjs/ts/py/goを使ってInfrastructure as Codeする

f:id:febc_yamamoto:20190912110915p:plain

はじめに

JavaScript/TypeScript/Python/Goを用いてInfrastructure as Codeできるpulumiさくらのクラウドに対応するためのプロバイダー(プラグインSDK)を公開しました。

www.pulumi.com

github.com

このプロバイダーを用いることで、以下のようなコードでさくらのクラウド上のリソースを操作可能になります。

さくらのクラウド上にサーバ(CentOS)を作成する例(TypeScript)

import * as sakuracloud from "@sacloud/pulumi_sakuracloud";

// CentOSパブリックアーカイブのIDを参照
const centOSArchive = sakuracloud.getArchive({osType: "centos"});

// CentOSパブリックアーカイブをコピー元とするディスクを作成
const disk = new sakuracloud.Disk("pulumi-example", {
    name: "pulumi-example",
    sourceArchiveId: centOSArchive.id,
});

// ディスクを接続したサーバを作成、ディスクの修正機能を利用してrootユーザーのパスワードを指定
const server = new sakuracloud.Server("pulumi-example", {
    name: "pulumi-example",
    disks: [disk.id],
    password: "YourPassword01",
});

// Outputとして作成したIDを指定
export const serverID = server.id;
export const diskID = disk.id;

この記事ではこのさくらのクラウドプロバイダーについて紹介します。

Pulumiについて

PulumiとはJavaScriptやTypeScript、Python、Goを利用してインフラの定義をコードで行えるプラットフォームです。
各種プログラミング言語を用いて宣言的にインフラのプログラミングを行うためのSDKやランタイム、CLIなどがオープンソースとして提供されています。

マルチクラウド対応を謳っており、AWS/Azure/GCP/Kubernetesなどに対応しています(他にも多数サポートしています)。
また、Pulumi社はCNCFのSilverメンバーでもあり、そのプロダクトPulumiもCNCF Landscapeに載ってたりします。

https://landscape.cncf.io/selected=pulumi f:id:febc_yamamoto:20190912121541p:plain

Pulumiについての概要は以下の記事などを参照ください。

Pulumiのファウンダー/CEOであるJoe Duffy氏のブログ

joeduffyblog.com

先日v1.0に到達

このPulumiですが、2019/9/5に正式版となるv1.0がリリースされました。

www.pulumi.com

Publickeyさんでも取り上げられていました。 www.publickey1.jp

この記事の執筆段階で早速v1.1がリリースされていましたので活発な開発が行われているようです。

Pulumiのさくらのクラウド対応

Pulumiでの操作対象は拡張可能

Pulumiで操作する対象となるインフラ/プラットフォームはプロバイダーという仕組みで拡張できるようになっています。

TerraformプロバイダーがあればPulumiプロバイダーを容易に作成可能

TerraformのプロバイダーからPulumiのプロバイダーを生成できるPulumi-Terraformブリッジというツールが提供されており、Terraformプロバイダーが用意されている環境であれば容易にPulumiプロバイダーを作成して利用できるようになっています。

参考: Pulumi vs. Terraform

github.com

余談ですがPulumiには元HashiCorp社のメンバーもJoinしてたりしますのでこの辺の連携が充実しているのも納得ですね。

今回リリースしたさくらのクラウド向けプロバイダーもTerraformプロバイダーを元に作成しました。
なのでさくらのクラウド向けのTerraformプロバイダーが対応しているリソースであればPulumiから利用可能となっています。

参考: Terraformのさくらのクラウドプロバイダー

Pulumi+さくらのクラウドプロバイダーの使い方

それでは早速利用方法についてみていきます。

Pulumiの基本的な使い方

Pulumiの基本的な使い方については公式ドキュメントのチュートリアルや以下の記事などを参照ください。

www.pulumi.com

dev.classmethod.jp

さくらのクラウドを使うための設定

Pulumiでさくらのクラウドを利用するにはPulumiプラグインのインストールが必要です。
以下のコマンドでプラグインをインストールできます。

$  pulumi plugin install resource sakuracloud 0.0.1 --server https://github.com/sacloud/pulumi-sakuracloud/releases/download/0.0.1

プロジェクトの作成 & さくらのクラウド向けSDKのインストール

次にプロジェクトを作成してさくらのクラウド向けSDKをインストールします。
空のプロジェクトを作ってnpmyarnpip3などを実行しても良いのですが、これらを簡単に行えるようにテンプレートを用意していますのでこちらを利用します。

Pulumiプロジェクトの作成

ディレクトリを作成してpulumi newコマンドを実行します。
pulumi newにはテンプレートの名前 or URLを指定します。

さくらのクラウド向けには以下のURLでテンプレートを提供しています。

  • JavaScript: https://github.com/sacloud/pulumi-sakuracloud/tree/master/templates/javascript
  • TypeScript: https://github.com/sacloud/pulumi-sakuracloud/tree/master/templates/typescript
  • Python: https://github.com/sacloud/pulumi-sakuracloud/tree/master/templates/python

例えばTypeScriptの場合は以下のようにします。

# ディレクトリの作成
$ mkdir example && cd example

# プロジェクトの作成
$ pulumi new https://github.com/sacloud/pulumi-sakuracloud/tree/master/templates/typescript

これを実行するとプロジェクト名やスタック名などの入力が求められます。
入力するとnpn installなどが実行されさくらのクラウド向けSDKのインストールが行われます。

注: Pythonの場合

Pythonの場合はpulumi new実行後に以下のように表示されます。任意のコマンドを実行してSDKをインストールしてください。

f:id:febc_yamamoto:20190912141228p:plain

APIキーの設定

(2019/9/12追記: 書き忘れてたため追記)

続いてさくらのクラウドAPIキーを設定します。 設定はpulumi config setコマンドや環境変数などで行えます。

今回は環境変数で行います。以下のコマンドで環境変数を設定しておきます。

$ export SAKURACLOUD_ACCESS_TOKEN=APIトークン
$ export SAKURACLOUD_ACCESS_TOKEN_SECRET=APIシークレット

プレビュー & デプロイ

あとは任意のコードを書いてプレビュー&デプロイするだけです。 先ほどのテンプレートはスイッチリソースを作成する内容となってますのでそのままプレビュー&デプロイ可能となっています。

プレビュー

$ pulumi preview

プレビューを実行すると実際にどのようなリソースが作成されるかが確認できます。

f:id:febc_yamamoto:20190912142320p:plain

デプロイ

次はpulumi upを実行して実際にリソースのデプロイを行ってみます。

f:id:febc_yamamoto:20190912142424p:plain

デプロイして良いか尋ねられますのでyesを選択するとデプロイされます。

f:id:febc_yamamoto:20190912142530p:plain

これでデプロイできましたね!!

お片づけ

pulumi destroyコマンドでリソースの削除ができます。 お試しの場合は忘れずに削除しておきましょう。

f:id:febc_yamamoto:20190912142656p:plain

おまけ: Terraformからの移行について

PulumiではtfファイルからPulumiのコードを生成できるtf2pulumiというツールも提供されており、Terraformからの移行を楽にしてくれています。

github.com

一からコードを書いても良いですが、こういったツールを利用することでコーディングが多少楽になるかもしれません。

終わりに

様々なプログラミング言語からInfrastructure as CodeができるPulumiとさくらのクラウドプロバイダーについて紹介しました。

リリースしたばかりでドキュメントなどが追いついていない場面もありますがぜひ使ってみてください!

以上です。

Terraform Cloud + さくらのクラウド プロバイダーを動かしてみる

Terraform Cloudがリリースされましたね!!

www.publickey1.jp

早速さくらのクラウドプロバイダーをTerraform Cloud上で動かしてみました。

Terraform Cloud事始め

通常のプロバイダーを使う手順はこちらに記事がありました。

dev.classmethod.jp

ワークスペースの作成〜VCS連携〜apply実行までの一通りの流れはこれに従えばOKです。

さくらのクラウドプロバイダーを使うには?

さくらのクラウドプロバイダーのような3rd プロバイダーを利用するにはちょっとした手順が必要になります。
この辺は以下にドキュメントがあります。

www.terraform.io

こちらによると、ワーキングディレクトリにterraform.d/plugins/linux_amd64/というディレクトリを作り、その中にlinux_amd64プラグインのバイナリを入れておけば良いとのことです。

他にもterraform-bundleを使う方法も用意されていますがこちらはTerraform Enterpriseのみですね。

febc-yamamoto.hatenablog.jp

ということでプラグインを配置した例を以下のリポジトリにおいてます。

github.com

tfファイル達と合わせるとこんな感じのレイアウトになりました。

f:id:febc_yamamoto:20190911115856p:plain

実行!!

あとはVariablesの設定などを行なってRunするだけです。今回はTerraform CloudのWebコンソールからRunしてみました。

まずはPlan

f:id:febc_yamamoto:20190911120120p:plain

問題なく動いているようです。このままApplyしてみました。

Apply

f:id:febc_yamamoto:20190911120146p:plain

ちゃんと作成されましたね!

Destroy

Destroyは不用意に削除されるのを防ぐためCONFIRM_DESTROY環境変数の設定が必要とのことでした。

f:id:febc_yamamoto:20190911120314p:plain

環境変数を設定すれば画面左下のボタンが押せるようになります。

あとはApplyと同じくPlan->Destroyするだけです。

f:id:febc_yamamoto:20190911120403p:plain

f:id:febc_yamamoto:20190911120427p:plain

終わりに

1チームあたり5ユーザーまで無料、それ以上の場合は有償版で$20/monthという価格となっています。

これはTerraformの実行環境として有力な選択肢となりそうですね!!
どんどん使っていこうと思っています。

以上です。