出力を入力へ

プログラミングに関する自分が考えた事を中心にまとめます

SRE NEXT 2020 に参加しました

2020-01-25 に開催された SRE NEXT 2020 に参加しました.

sre-next.dev

現在自分はインフラエンジニアとして働いており, 運用も合わせて行っているので勝手に自分もSREを名乗れるかな?と考えて 自分が今後目指すべきキャリアを見極めようと考えて参加しました.

以下自分が聴講したセッションとその感想です.

[A0]基調講演: 分散アプリケーションの信頼性観測技術に関する研究

さくらインターネットにおける(というより発表者の?)SREを研究に昇華させた取組み.

speakerdeck.com

単なるアプリケーションの信頼性に限らず,クラウドを構築・提供する事業者としてのサービスの信頼性を どのように取組むかといった将来のSREに向けた取組みであると,まさにSRE NEXT だった.

一方で,これは今自分が取組む内容とはかけ離れていて,同じSREでもここまで違うんだな,と他人事に思えた. 最後のパネルディスカッションの中で,将来のSREはアプリ開発の中に原則は残りつつも, 究極的にはクラウド事業者だけが気を付ければいい職掌になる,といった内容の話があり, この基調講演の他人事のように思えた感じはクラウド事業者とクラウド利用者の差なのだなと感じた. だとすると,この発表のようなクラウド事業者としてのSRE NEXT ではなく, サービス開発者側のSRE NEXT を探さないといけない.

[C1] 絶え間なく変化するメルカリ・メルペイにおけるSREの組織と成長

メルカリおよびメルペイにおけるSREを組織化するに向けて取り組んできた成果.

speakerdeck.com

メルカリとメルペイで (マイクロサービス化できているかという視点から)組織構成や取組みが異なることは初めて知ったし, これだけ技術的に優れているメルペイであってもSREがチームとして動くようになるまでには大きな苦労を伴うことは, どこでも簡単ではないんだなと現実を知った感じ.

ただ,どちらの発表もなぜそうなったのか,どうやってそうしたのかというプラクティスがあまり共有されなかったのが残念だった. メルカリのマイクロサービス移行の過去の取組みとしてchocon開発移行の状況は紹介されていても, SREがボトルネックになりそうという問題があまり理解できなかったし,組織編成でどうして解決できるのかも伝わらなかった. 時間があれば聞いてみたかったところ. メルペイもToilを受け入れて戦う必要があるし採用は辛い,チーム化も辛いと,課題はよくわかるのだけれど, サービスがリリースされたら採用できました,人が増えたら解決できました,と聞こえてしまい, どのようにToilを対処したのか,どのように頑張ったのかがわからなかった.

[C2] 成長を続ける広告配信プラットフォームのモニタリングを改善してきた話

Voyage におけるアラートや監視の取組み.

speakerdeck.com

ユーザ視点でサービスが正常であるかを判断し,サービスの外側から重点的に監視するというのは, あたりまえではあるけどその通りだと思った.実際,自分のところではできていないから対処しないといけない. アラートも目的に応じて通知先をふりわけるというのも必要なこと. それでSREが楽になるだけでなく開発者も気にしてくれるようになるのであればこれ以上はない. アラートの見直しは障害が起きたとき,監視システムを置き換えたとき,人が増えたとき,というのはなるほどと思った. 障害が起きたときの見直しは当然だけど,人が増えたときにそれを切っ掛けにするというのは 大変だけど効果がありそうなので取組みたい.

ツール選択には複数の指標をもとに,ツールと仲良くなって判断するというのも, なかなかできていないので耳が痛い話.もっと普段からいろいろ挑戦してみないと.

[D3] Practices for Making Alerts Actionable

グリーにおける静観対応となるアラートの問題と, アラートの計測とふりかえりによるアラートの見直し,自動復旧の検討の取組み紹介.

speakerdeck.com

最近自分のところでもアラートの対応に課題があることは認識しており, どのように対応すべきか考えていたのでとても参考になった.

アラートに問題があるならアラートを計測してふりかえるという, あたりまえのことにきちんと取組めているのはすばらしいと思うしぜひ真似していきたい. 自動復旧も,既に障害で動いていない場合などこれ以上悪くならない場合には 導入しやすいというプラクティスもその通りなのでぜひ取組みたい.

[D4] 100万回線のIoT通信を支えるソラコムにおけるOpsDevの実践

ソラコムにおけるOpsDev (=SRE)の取組み.

www.slideshare.net

開発者も運用をするし,開発者もSREもサポートをするし,インシデント通知はエンジニア以外の全社員に通知するのは,すごい取組みだと思った. これがきちんと実践できているのであれば,サービスの信頼性や顧客満足度を全員が意識するようになるので, カルチャーとしてはすばらしいと思う.

ただ,カスタマーサポートも非常に難しい職掌だし,エンジニアと兼務して取組める気がしない. エンジニアのスキルだけでもキャッチアップするのが大変な,さまざまな技術が求められる時代なのに, 加えてカスタマーサポートもは自分だったら対応できない. どのようにエンジニアがサポートを実践しているのか, どのようにバックオフィス系の社員が障害アラートを認識して対応しているのかは気になるところ.

[C5] スクラムを1年回してSREと開発組織がどう変わったのか

HAMOS(ビズリーチ)におけるSREとしてのスクラムの取組み. 特定のタスクに取組めず,割り込みの多いSREがどのようにスクラムを実践してきたか紹介があった.

speakerdeck.com

どれに取組めばいいのかわからないので,タスクの優先度を定量的に評価することで全員が合意の元で判断できるようにする,というのはすばらしい取組み. 一方で,タスクの優先度を定量化するのはそう簡単ではなく, 下手をすれば設定したい優先度に向けて定量化の式を毎回見直したくなる気がする.

開発チームとの共依存について, ペアプロ等で相互に技術移管して割り込みで他者に仕事を依頼するのではなく, 自分ごととして対処できるようにするというのは理想的な状態. 現状,自分たちではまだまだ1人がやることが多くて技術移管までできそうにないのが辛いところ. このあたりは属人化の問題と関連しているのだろうけれど, どうしてもスピードが優先されるスタートアップにおいてなかなか 長期的な運用を見据えてスピードを犠牲にする判断はできない. 自分たちの取組みが必要なところかも.

[C6] Designing fault-tolerant microservices with SRE and circuit breaker centric architecture

クックパッドにおける既存のアプリの信頼性を担保しつつも機械学習サービスなど新しい技術領域を取り入れていく取組み.

このあたりは自分たちも近い将来同じ課題にぶつかることが想定されるので非常に参考になった. とはいえ,機械学習エンジニア側で開発リソースや自分たちで運用することができる前提なので なかなか同じようにはいかなそう. それでも信頼性の異なるサービスをサーキットブレイカーで分けるとか, デザインドキュメントで期待値をすりあわせるとか,できれば自分たちも取り入れたい.

若干ながら機械学習チームをつき離しているようにも聞こえたが, 何が大切なのかを共有できており,相互に信頼・尊重しているからこそできる無駄のない取組みだろう. そのようなチームができるように自分たちも頑張りたい.

[B7] SRE Practices in Mercari Microservices

メルカリにおけるマイクロサービスを実践していく中での,SLI/SLOを更新し続けるための取組み,オンコールへの対応,Toil(リアクティブなタスク)への取組み.

speakerdeck.com

これまでの発表内容が随所に出てくる,まさにロングセションに相応わしくSREの個々のプラクティスが一本にまとまるようで聞いていて非常に面白かった.

SLI/SLOを始めから完璧を目指さず更新していく体制を整えること,それを実現するためのポストポーテムの実践と SLO Decision Matrixを参考にしつつも 内容に応じて自分たちで判断することこは理想的なチームであるように見える.

アラートをアクション可能として,REDでアラートしてUSEで調査するという, 障害対応とはこのように実践するんだといわんばかりの体制だった.

Toilを減らしリアクティブなタスクに対処するため, デザインドキュメントで期待値を調整し,Production Readiness Checkでチェックするというのは 開発者とサービスリリース後にもめないためのリスクを減らす仕組みとしてよさそう. 一方でこれを実践しても形骸化せずサービスの品質に落とし込めるのは メルカリの優秀なエンジニアがいてこそだろうか.

[A8]基調講演: Webサービスを1日10回デプロイするための取り組み

Lobi(面白法人カヤック)における 10 deploy per dayを実現するために, デプロイを構成するあらゆる要素の高速化と誰でも安全にデプロイできる仕組みを実現する取組み.

speakerdeck.com

デプロイを高速化するためにエラー検知やロールバックを含めて高速化するところはなるほどと気付きを得た. 安全に誰でもデプロイできるようにするために,自動化するのはもちろん,計測して管理するのも王道だしよいプラクティスだと思った.

自分のところでは,デプロイが大変だと認識していてもまだデプロイも自動化できていない. デプロイ作業を計測して,デプロイの大変さを再共有し,自動化に向けた対応を強化するのはいいかもしれない. ChangeLogの生成自動化もやりたいところなので,早めに完了させたい.

全体をふりかえって

自分にもすぐに取組めそうなプラクティスから,すぐには取組めないけど将来の目標に見据えられるようなすばらしい取組みまで, さまざまな知見を共有できたすばらしい1日だった.

今までは先進技術として面白く感じていても他人事であったのが, やっと自分もインフラエンジニア・SREエンジニアとなって自分ごととなり, 自分事という新しい視点で話を聞けて非常に刺激になった.

取り入れられるプラクティスは積極的に取り入れて 今度は自分が発表する側に立てるようになりたい.

TerraformでAWS管理ポリシー/カスタム管理ポリシー混合のロールを作成する

なんで悩んでいたのかわからない.

ロールにアタッチするポリシーのうち, AWS管理ポリシーをアタッチする場合は data.aws_iam_policy で対象のarnを指定する, カスタム管理ポシリーをアタッチする場合は resource.aws_iam_policyでポシリーを作成してarnを指定する. アタッチはどちらも resource.aws_iam_policy_attachment を利用すればよい.

dataとresourceをきちんと理解していなかった.反省.

resource "aws_iam_role" "terraform_sts_role" {
  name = "terraform-sts-role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

resource "aws_iam_policy" "custom_s3_list_bucket" {
  name = "CustomS3ListBucket"
  path = "/"

  policy = <<POLICY
{
  "Statement": [
    {
      "Action": [
        "s3:ListAllMyBuckets",
        "s3:ListBucket",
        "s3:HeadBucket"
      ],
      "Effect": "Allow",
      "Resource": "*",
      "Sid": "VisualEditor0"
    }
  ],
  "Version": "2012-10-17"
}
POLICY
}

resource "aws_iam_policy_attachment" "attach_custom_policy_to_sts_role" {
  name       = "CustomS3ListBucket"
  policy_arn = aws_iam_policy.custom_s3_list_bucket.arn
  roles      = [ aws_iam_role.terraform_sts_role.name ]
}


data "aws_iam_policy" "ec2_read_only_access" {
  arn = "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"
}


resource "aws_iam_policy_attachment" "attach_ec2_read_only_access_to_sts_role" {
  name       = "EC2ReadOnlyAccessAttachment"
  policy_arn = data.aws_iam_policy.ec2_read_only_access.arn
  roles      = [ aws_iam_role.terraform_sts_role.name ]
}

実践Terraform AWSにおけるシステム設計とベストプラクティス (技術の泉シリーズ(NextPublishing))

実践Terraform AWSにおけるシステム設計とベストプラクティス (技術の泉シリーズ(NextPublishing))

書評:DNSがよくわかる教科書

DNSはなんとなくはわかるけど詳しいことは理解できていない, という状況の中で発売され評判もよかった本. やっとのことで読む時間を確保できたので読んだけど, 実際すごくよかった.

概要

DNSの仕組みから運用ノウハウまでを解説した本. 大きく3部構成で,DNSとは何かから学べる基礎編, 実際にネットワークを構築しDNS設定を行う設定やDNSを運用するときに必要な知見を記載した実践編, 運用のノウハウやセキュリティまわりの動向を扱ったアドバンス編で構成されている.

よかったところ

正確な表現を利用しつつも,わかりやすい解説があったことが良かった. インターネット上で調べると用語や説明がわかりにくいか,場合のよっては間違えているものが多く 理解の妨げになっていたけど, 世の中における誤りを指摘しつつ正しい用語で説明してくれたので理解が進んだ. その中でもわかりやすさを重視して解説してくれたおかげで, 途中で理解が迷子にならず読み進めることができた.

また,教科書というだけあって,一通りのトピックを扱っているので 知識の抜けがなく全体を俯瞰できたのはよかった. 加えてよくある誤りや設定ミスも記載されており, どういった点に注意すればよいかも理解しやすい.

8章のDNSの動作確認では実際にコマンドを使ってDNSの動きを理解できたこと, 9章のDNSに関するサイバー攻撃の分類と解説, 11章のDNS設定でよくある誤り, は特に参考になった.

よくなかったところ

全体をコンパクトにまとめることを重視したせいかもしれないけれど, もう少し説明が欲しい章はいくつもあった. 個人的には特にリソースレコードやDNSSECはもう少し詳しく扱って欲しかった. DNSの動作検証用のサイトとして取り上げた3つのDNSチェックサイトも どう見ればいいのか理解できていないでいる.

まとめ

DNSに対する苦手意識は払拭できたし, 今後どこの技術領域を調べればいいのかわかるようになった という点で非常によかった. インフラ/ネットワークを扱う人なら誰でも1度はDNSで つまずいた経験はあると思うので, そういう人には間違いなくお勧めできる. 基礎編はインフラを扱う人でなくても1度読んでおいて欲しいくらい.

GitHub Actionsのsteps.withディレクティブでは環境変数ではなく出力パラメータを利用する

タイトルがすべて.

steps.with ディレクティブにおける制御

GitHub ワークフローにてActionsを呼び出すとき, Actionsのパラメータ設定としてsteps.withディレクティブを利用する.

例えば,GitHubのリリースページにビルド成果物をアップロードする Upload Release Asset Actions では以下のように指定する.

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Upload Release Asset
        id: upload-release-asset 
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./my-artifact.zip
          asset_name: my-artifact.zip
          asset_content_type: application/zip

ここで, steps.withディレクティブ以下の upload_url, asset_path, asset_name, asset_content の4つが upload-release-asset Actionsの入力パラメータである.

入力パラメータの動的制御

Releaseページにアップロードするファイルを指定する asset_path において, ビルドソフトウェアのバージョンが含まれたファイルを指定したい. ソフトウェアバージョンを環境変数に設定したとして, 以下のような利用方法を想定する.

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Set software version
        run: |
          VERSION=$(cat VERSION)
          echo ${ VERSION }
      - name: Upload Release Asset
        id: upload-release-asset 
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./my-artifact-${ VERSION }.zip
          asset_name: my-artifact-${ VERSION }.zip
          asset_content_type: application/zip

このように,VERSIONファイルに格納されているソフトウェアバージョンをVERSION変数に格納し, ビルド成果物の制御にこの値を利用したい. しかし,この方法には以下の2つ問題がある

このため,Set software versionのステップにおける echo ${ VERSION }では期待した通りの値が出力されるが, Upload Release Assetのステップではそんなファイル存在しない (##[error]ENOENT: no such file or directory )と怒られてしまう. これは,VERSION 変数が設定されていない問題と,仮に設定されていたとしてもその変数を利用できない問題の両方を解決する必要がある.

出力パラメータによる制御

ではどうするかと言うと環境変数ではなく 出力パラメータ(output parameter)を利用しましょう,というのが解決策である. 出力パラメータは別のステップから出力結果を参照するための仕組みであり, steps.withディレクティブでも利用できる.

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Set software version
        id: software_version
        run: |
          VERSION=$(cat VERSION)
          echo ::set-output name=version::${ VERSION }
          echo ${ VERSION }
      - name: Check output parameter value
        run: |
          echo ${{ steps.software_version.outputs.version }}
      - name: Upload Release Asset
        id: upload-release-asset 
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./my-artifact-${{ steps.software_version.outputs.version }}.zip
          asset_name: my-artifact-${{ steps.software_version.outputs.version }}.zip
          asset_content_type: application/zip

このように, Set software version ステップにて VERSION変数の値を出力パラメータに設定しているので, 後段の Check output parameter value では最初に設定した VERSION 変数と同じ出力を確認することができ, Upload Release Assetステップの asset_pathasset_name でも利用することができる.

Requestsで取得したwebサイトの文字化けに対処する

Requestsで取得したWebサイトをlxmlスクレイピングしようとすると, いくつかのサイトで文字化けすることに気が付いた.

これに対処するのに苦労したし,何ならまだ完全には解決できていない. 間違いとかあれば教えて欲しい.

文字化けの確認

例えば O'reillyのサイトだと文字化けが発生する. webサイトのタイトルを出力するPythonスクリプトは以下の通り.

import requests
import lxml.html

res = requests.get('https://www.oreilly.co.jp/books/9784873118864/')
root = lxml.html.fromstring(res.content)

print(root.xpath('//title')[0].text)

このスクリプトの実行結果は以下の通り

O'Reilly Japan - ã¬ã¬ã·ã¼ã³ã¼ãããã®è  ´

上記サイトはタイトルに「O'Reilly Japan - レガシーコードからの脱却」が指定されており, この通り出力して欲しい.

このブログでもダメ.

'å\x87ºå\x8a\x9bã\x82\x92å\x85¥å\x8a\x9bã\x81¸'

一方で,Yahooニュースなら正常に動作する.

'Yahoo!ニュース'

原因

もちろんエンコーディングの指定誤りが原因で, Requests で取得したwebサイトの文字コードを正しく識別できていないことが原因. これについては,以下のサイトが詳しい.

orangain.hatenablog.com

実際,HTTPレスポンスを確認すると

$ wget --server-response https://www.oreilly.co.jp https://www.oreilly.co.jp/books/9784873118864/
...
HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Date: Sat, 12 Oct 2019 16:42:53 GMT
  Content-Type: text/html
  Content-Length: 23094
  Connection: keep-alive
  Server: Apache
  Last-Modified: Thu, 10 Oct 2019 05:06:47 GMT
  ETag: "5a36-594875e4b2e01"
  Accept-Ranges: bytes
  Vary: Accept-Encoding

...

$ wget --server-response https://thaim.hatenablog.jp/ 
...
HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Server: nginx
  Date: Sat, 12 Oct 2019 16:25:25 GMT
  Content-Type: text/html; charset=utf-8
  Transfer-Encoding: chunked
  Connection: keep-alive
  Vary: Accept-Encoding
  Vary: User-Agent, X-Forwarded-Host, X-Device-Type
  Access-Control-Allow-Origin: *
  Content-Security-Policy-Report-Only: block-all-mixed-content; report-uri https://blog.hatena.ne.jp/api/csp_report
  P3P: CP="OTI CUR OUR BUS STA"
  X-Cache-Only-Varnish: 1
  X-Content-Type-Options: nosniff
  X-Dispatch: Hatena::Epic::Web::Blogs::Index#index
  X-Frame-Options: DENY
  X-Page-Cache: hit
  X-Revision: a7694746800267be0e2d318311d7b13e
  X-XSS-Protection: 1
  X-Runtime: 0.042860
  X-Varnish: 34747135
  Age: 0
  Via: 1.1 varnish-v4
  X-Cache: MISS
  Cache-Control: private
  Accept-Ranges: bytes
...

$ wget --server-response https://news.yahoo.co.jp 
...
HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Cache-Control: private, no-cache, no-store, must-revalidate
  Content-Type: text/html;charset=UTF-8
  Date: Sat, 12 Oct 2019 16:26:09 GMT
  Set-Cookie: B=1qlmjdleq3vl1&b=3&s=l0; expires=Tue, 12-Oct-2021 16:26:09 GMT; path=/; domain=.yahoo.co.jp
  Vary: Accept-Encoding
  X-Content-Type-Options: nosniff
  X-Download-Options: noopen
  X-Frame-Options: DENY
  X-Vcap-Request-Id: 9826dce8-3f25-4d7b-7749-c0e9fdcd8fba
  X-Xss-Protection: 1; mode=block
  Age: 0
  Server: ATS
  Transfer-Encoding: chunked
  Connection: keep-alive
  Via: http/1.1 edge2502.img.umd.yahoo.co.jp (ApacheTrafficServer [c sSf ])
  Set-Cookie: XB=1qlmjdleq3vl1&b=3&s=l0; expires=Sat, 19-Oct-2019 16:26:09 GMT; path=/; domain=.yahoo.co.jp; secure; samesite=none
...

そう,実ははてなブログではContent-Typeが適切に設定されているのに上手くいかない. 文字コードを小文字で指定しているのが原因かとも思ったけれど RFCによるとどちらでもよいみたい.

tools.ietf.org

requestsは chardet文字コードの 推定も行っているので確認してみたけど, ブログもYahooニュースもどちらもUTF-8を認識している.

>>> import requests, lxml.html
>>> res = requests.get('https://thaim.hatenablog.jp/')
>>> res.encoding
'utf-8'
>>> res.apparent_encoding
'utf-8'
>>> res = requests.get('https://news.yahoo.co.jp/')
>>> res.encoding
'UTF-8'
>>> res.apparent_encoding
'utf-8'

これについてはお手上げで, なぜYahooニュースでは上手くいくのに はてなブログでは上手くいかないのかわからなかった.

対策

根本原因がどうであれ, 正しく文字コードを指定して処理すればいいだけなので, この問題を解決するだけならlxmlでスクレイピングする前に文字コードを指定してデコードしてあげればよい.

意図した通り動作するスクリプトは以下の通り.

import requests
import lxml.html

res = requests.get('https://www.oreilly.co.jp/books/9784873118864/')
root = lxml.html.fromstring(res.content.decode('utf-8'))

print(root.xpath('//title')[0].text)

ここでは,UTF-8で固定しているけれど, res.apparent_encoding を指定したり,HTML内で文字コードを指定されているのであればそれに従う方法もある.

Terraform backendsのパラメータ化にPartial Configurationを利用する

Terraform Backends

対象インフラの状態を管理するtfstateファイルをチーム共有・管理するためにbackendを利用する.

www.terraform.io

例えば,AWS S3をバックエンドに利用する例は以下の通り. これによりS3でtfstateファイルを管理できる.

terraform {
  backend "s3" {
    bucket = "my-tfstate"
    key    = "sample-project/prod.tfstate"
    region = "ap-northeast-1"
  }

  required_version = "= 0.12.2"
}

backendにおける設定のカスタマイズ

上記設定においてバケット名やkey(ファイル名)をパラメータ化して実行時に指定したい.

バケット名はGitで公開したくない,keyは開発/検証/本番 環境によって切り替えたい といった要望に対応するため,各種設定項目に変数を利用したい. 場合によってはアクセスキーやシークレットキーの指定も必要で, その場合は特にGit以外で管理する必要がある.

これを解決するために,パラメータ部分に変数を利用したい

tf_backend_bucket = "my-ftstate"
tf_backend_key    = "sample-project/prod.tfstate"
variable "tf_backend_bucket" {}
variable "tf_backend_key" {}

terraform {
  backend "s3" {
    bucket = var.tf_backend_bucket
    key    = var.tf_backend_key
    region = "ap-northeast-1"
  }

  required_version = "= 0.12.2"
}

しかし,このような方法でterraformを実行してもエラーになる. backendの設定には変数は利用できない.

$ terraform init

Error: Variables not allowed

  on main.tf line 3, in terraform:
   3:     bucket = var.tf_backend_bucket

Variables may not be used here.


Error: Variables not allowed

  on main.tf line 4, in terraform:
   4:     key    = var.tf_backend_key

Variables may not be used here.

解決策

バックエンドのパラメータ化には変数ではなく Partial Configuration を利用する. Partial Configurationでは,terraform init実行時のオプションとして -backend-config を指定する.

  -backend-config=path This can be either a path to an HCL file with key/value
                       assignments (same format as terraform.tfvars) or a
                       'key=value' format. This is merged with what is in the
                       configuration file. This can be specified multiple
                       times. The backend type must be in the configuration
                       itself.

key=value 形式で指定するなら以下の通り:

$ terraform init -backend-config="bucket=my-tfstate" \
                 -backend-config="key=sample-project/prod.tfstate"

設定ファイルに書くなら以下の通り:

$ terraform init -backend-config="backend.tfvars"
bucket="my-tfstate"
key="sample-project/prod.tfstate"

このとき,backendの設定は空欄とする.

terraform {
  backend "s3" {
    region = "ap-northeast-1"
  }

  required_version = "= 0.12.2"
}

あらかじめデフォルト値を設定しておいてもよい. -backend-configオプションで指定すると上書きできる.

また,tfファイルで未設定のまま-backend-configで指定しないと インタラクティブに入力が求められる.

backendに Partial Configurationではなく 変数を利用したいというIssueは挙がっているけど, 対応される見込みはなさそう.

GoCon 2019 Springに参加しました

半年に1度のGo言語に関するカンファレンスのGo Conference 2019 Springに参加しました.

自分はGo言語は読む方がメインで,少し書く程度というGo言語初心者. そんな自分でもカンファレンス発表内容はGo言語自体の話だけではなく, Go言語を用いたソフトやシステムの話など幅広いトピックを扱っており, 非常に刺激になった.

gocon.jp

gocon.connpass.com

以下自分が聴講したセッション

keynote: Go Module Proxy Life of a Query

github.com

go modulesの話はなんとなく知っていた程度なので, 正直なところ概要しか理解できなかったのが残念だった. 発表のKatieさんの英語は聞きやすかったけど,前提知識が異なる場合は自分の英語力もまだまだだと実感した. 特にChecksum Databaseの話が難しかった.

前提知識としては,公式のブログ記事を 理解しておけばもう少し楽しめただろうか? とはいえ,Mirror (module proxy) の話は面白かったし, どの程度データ量等削減されるのかは試してみたい.

A1: Case Studies of designing developer friendly libraries

speakerdeck.com

内容としてはGo言語に限らない話で,かつGo言語の場合は特にどうなのかしっかりまとめられていた. なので自分みたいなGo言語以外をメインに利用している人には特に刺さると思った. 実際, context.Context の話とか自分の実装は適当だったなと反省した.

B2: エラー設計について / Designing Errors

docs.google.com

エラー設計はまさに悩んでいるところだったのでちょうど良い内容だった. failure とその設計思想を知れたのはよかった. 一方で自分で書くgoアプリは小規模なものなので,エラーハンドリング用パッケージの導入まで必要かは検討の余地がある. このあたりはいろいろ試行錯誤してみたい.

A3: Goによる外部プロセス起動ベストプラクティス及びtimeoutパッケージ徹底解決

songmu.github.io

goの外部プロセス停止に関する仕組みを調査・実装する上で, オフィシャルの見解の確認やGNU timeoutをベースとした知見の流用など, 開発の取り組み方がすばらしいと感じた. おまけにあたる終了コードを正しく取得するという内容も, 自分もきちんと考えていなかったことを再認識したので聞けて良かった.

A4: Design considerations for container-based Go applications

speakerdeck.com

どちらかと言うとコンテナの話がメインで,基本がしっかりと抑えられていた. 一方でGoの方はあっさりと結論だけ示されている形式だったので, Go初心者の自分としてはもう少しこのあたりの試行錯誤などが気になった. 実際に自分で実装するとき,他の実装方法やPros/Consがないかは自分でいろいろ考えてみたい.

A5: Expand observability in Go

docs.google.com

パフォーマンスチューニングの話は現状まったく取り組めていないので とっかかりになればいいなと考えていたけど, パフォーマンスチューニングの基礎から実際にどのように取り組めばよいか, デモ付きで話を聞けたのはすごくよかった. 忘れないうちに実践してみたいところ.

H6: Dive into Buildkit LLB with Go

speakerdeck.com

Dockerイメージ生成のはなしは概要レベルでしか把握できていなかったのでそれが ソースコードレベルで知れたのはよかった. Dockerfileの静的解析の話とかは度々出てくるので, 実際に手を動かして試してみるためのとっかかりになりそう. Docker / BuildKit は自分がGo言語を始めるきっかけでもあったので このレベルで理解できるようになりたい.

H7: We want AWESOME CLI tool & development

speakerdeck.com

Golden fileについては知らなかった. 参考となるリポジトリを複数挙げていたのは 実際に自分が実装するときの参考になるので助かる. 複数プラットホームにおけるHOMEの取得は, 標準でも対応しているみたいなので別途確認しておきたい.

B8: CPU, Memory and Go

speakerdeck.com

あまり詳細なGo言語の実装等の話になると理解できなくなるから困るなと心配していたけど, 計算機の基礎からC言語との比較までと,自分が理解できるちょうどいい内容だった. むしろ最近はこの手の話から遠ざかっていたのでいい復習になった. メモリの話がメインだったのでもう少しCPUや実行速度の話が気になった.