helloworlds

not a noun, it's a verb

【Airflow】入門 part.1

概要

Airflowとは、ワークフローエンジンの1種。

実行するタスクの依存関係をDAGを定義し、スケジュールや監視を設定したりしてタスクを実行させる。

Airflow Guides ( https://github.com/astronomer/airflow-guides ) 公式ドキュメント( https://airflow.apache.org/docs/stable/ )

GCPではAirflowのマネージドサービスであるCloud Composerというサービスが存在する。 Cloud Composerを手軽に利用するには、コストがかかるので、Docker(docker-airflow)を開発では利用する。

※この記事では、Airflowの起動までを記載しています。

アーキテクチャ

f:id:o21o21:20200910121446p:plain

引用: https://github.com/astronomer/airflow-guides/blob/master/guides/airflow-components.md

4つの主なコンポーネントが存在。

  • Webserver: UI
  • Scheduler: ジョブのスケジューリング
  • Executor: 実際にワークが行われるメカニズム
  • Metadata Database: 他のコンポーネントの相互作用を決定するデータベース(通常はPostgres)

docker-airflowをインストールしてみる

リリースされているdocker-airflowは以下。

github - docker-airflow

Docker

Dockerをココ(mac用)からインストール。

docker-compose-LocalExecutor.ymlを配置

docker-compose-LocalExecutor.ymlというファイルを任意のディレクトリに配置します。

## 例
$ mkdir test-airflow
$ mv docker-compose-LocalExecutor.yml.yml ~/test-airflow/

ここでExecutorを指定することになるようです。 Executorとは、メッセージのキューイングするプロセス。 スケジューリングした各タスクを実際に実行するWorkerプロセスを決定する役目。

  • SequentialExecutor: Schedulerプロセスと同じマシン上でタスクをシーケンシャルに処理する
  • LocalExecutor: Schedulerプロセスと同じマシン上でタスクを並列処理する
  • CeleryExecutor: Workerマシンのクラスタにタスクを分散して並列処理する

コンテナの構築・起動

docker-compose-LocalExecutor.ymlを配置したディレクトリで以下を実行。

$ docker-compose -f docker-compose-LocalExecutor.yml up -d

以下にように、doneと表示されればおk。

Pulling postgres (postgres:9.6)...
9.6: Pulling from library/postgres
5e35bd43cf78: Pull complete
0df82dab3c88: Pull complete
0670a6d74375: Pull complete
bd2be22379ef: Pull complete
9eb829e5b266: Pull complete
95d7f9aaa5bd: Pull complete
de97a90167ed: Pull complete
4b50288dfea5: Pull complete
1de3ac04528c: Pull complete
80ae7e788989: Pull complete
03206c3e9141: Pull complete
583f3a17a7fc: Pull complete
630a4a9106e6: Pull complete
9a4e5c50216a: Pull complete
Digest: sha256:afe4d4a6b5c5dff5377944d0922636614cf695204e289d68ff91f0c658e84205
Status: Downloaded newer image for postgres:9.6
Pulling webserver (puckel/docker-airflow:1.10.9)...
1.10.9: Pulling from puckel/docker-airflow
bc51dd8edc1b: Already exists
dc4aa7361f66: Already exists
5f346cb9ea74: Already exists
a4f1efa8e0e8: Already exists
7e4812fc693b: Already exists
ff8fd055a548: Pull complete
c9215f8e7f2f: Pull complete
cab2fe472084: Pull complete
1f03789c1e57: Pull complete
Digest: sha256:30e7cb9744ad367c54ae30a379fa46c9df4ea582bf2fcb96604adfc2760be79a
Status: Downloaded newer image for puckel/docker-airflow:1.10.9
Creating test_20200415_postgres_1 ... done
Creating test_20200415_webserver_1 ... done```

dockerのimageとコンテナを確認

$ docker images

REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
postgres                9.6                 11467448d371        14 hours ago        200MB
puckel/docker-airflow   latest              ce92b0f4d1d5        2 months ago        797MB
puckel/docker-airflow   1.10.9              3e408baf20fe        2 months ago        797MB
$ docker ps 

CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                             PORTS                                        NAMES
d1f3f6b8843a        puckel/docker-airflow:1.10.9   "/entrypoint.sh webs…"   16 seconds ago      Up 15 seconds (health: starting)   5555/tcp, 8793/tcp, 0.0.0.0:8080->8080/tcp   test_20200415_webserver_1
b75c125de3f5        postgres:9.6                   "docker-entrypoint.s…"   16 seconds ago      Up 15 seconds                      5432/tcp                                     test_20200415_postgres_1

postgresのヴァージョン指定などをしたい場合は、さきほど配置したdocker-compose-LocalExecutor.ymlの中身を編集することで、ヴァージョンの指定が可能だと思います。

ここまで確認できたら、一旦ブラウザでもUIが表示されるか確認します。

ブラウザで確認

http://localhost:8080

↑上記にアクセスしてみます。

無事にこのような画面が表示されれば起動は成功です。

f:id:o21o21:20200910121554p:plain

<project_name>/
├── dags                        ## ← ここにDAGを定義するファイルを作成していく
└── docker-compose-LocalExecutor.yml

終わりに

ここまでで起動は確認できました。

AIrflowの機能であるDAGの作成やDB(Postgres)の永続化など、他の事項はまた別記事にて記載します!

以上.

【Javaのインストール】macOSにJavaをインストールする (2020)

以前、このような記事を書きました。

o21o21.hatenablog.jp

macOSを使用していて、色々とJavaには環境構築でパッと記事が出てこないので忘れてしまいます。。

なので、2020年版、macOSJavaをインストールしよう!を記載していきます。

前提

  • homebrewがインストールされていること

手順

brewコマンドを叩く

brew installはよく使うけど、brew tapとは?って思う人もいるかと思います。

brew tapとは

公式以外のformula(パッケージ名(元は方式とか形式という意味))を追加すること

docs.brew.sh

なので、以下のコマンドを実行します。

$ brew tap AdoptOpenJDK/openjdk
$ brew cask install <version>

わたしは試しに、 brew cask install adoptopenjdk8を実行しました。

==> Tapping homebrew/cask
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 473568 (delta 0), reused 0 (delta 0), pack-reused 473564
Receiving objects: 100% (473568/473568), 213.92 MiB | 12.09 MiB/s, done.
Resolving deltas: 100% (335714/335714), done.
Tapped 1 command and 3641 casks (3,759 files, 229.3MB).
==> Downloading https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u265-b01/OpenJDK8U-jdk_x64_mac_hotspot_8u265b01.pkg
==> Downloading from https://github-production-release-asset-2e65be.s3.amazonaws.com/140418865/6444de00-d246-11ea-8be7-50169d929f88?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F2020
######################################################################## 100.0%
==> Verifying SHA-256 checksum for Cask 'adoptopenjdk8'.
==> Installing Cask adoptopenjdk8
==> Running installer for adoptopenjdk8; your password may be necessary.
==> Package installers may write to any location; options such as --appdir are ignored.
Password:
installer: Package name is AdoptOpenJDK
installer: Installing at base path /
installer: The install was successful.
package-id: net.adoptopenjdk.8.jdk
version: 1.8.0_265-b01
volume: /
location: Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk
install-time: 1598319592
🍺  adoptopenjdk8 was successfully installed!

詳しい情報は以下を参考にしてみて下さい。

GitHub - AdoptOpenJDK/homebrew-openjdk: AdoptOpenJDK HomeBrew Tap

確認

$ java -version
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_265-b01)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.265-b01, mixed mode)

1.8.0_265 この数値をみていくと、

バージョン番号が8

もう少し詳しく確認する。

$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -V

Matching Java Virtual Machines (1):
    1.8.0_265, x86_64:  "AdoptOpenJDK 8"    /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home

うん、これだと先程インストールしたAdoptOpenJDK 8だとわかりやく確認できました。

以上.

【AWS】Lambdaの環境変数の暗号化でバグ!? 

仕事が忙しく、なかなか更新できていませんでしたが、また徐々にためていた記事をアップできたらと思います!

事象

Lambda関数が、KMS(CMK)を利用し暗号化している環境変数の値を復号し、プログラムを実行する場面があった。 しかし、復号に失敗し続けている事象が発生。

確認したこと

  • CMK
  • キーのタイプ
  • キーの仕様
  • キーポリシー (ポリシーは、json形式で確認可能)
  • キーの使用("暗号化および復号化"になっているか)

  • Lambda

  • 設定した環境変数の値(そもそも)
  • 暗号化に使用したCMKは、適切なCMKで暗号化してるか(そもそも)
  • LmbdaにアタッチしているRole 

  • その他関連しそうなサービスのPolicyなど

Lambdaに関しては、環境変数に編集でKMSの使用を設定できる。

f:id:o21o21:20200820095733p:plain

転送時の暗号化に使用するヘルパーの有効化←にチェックを入れることで、環境変数値の横に暗号化のボタンが表示される。 暗号化したいデータを入力し、暗号化を押下すると、暗号化に使用するKMS(CMK)を選択できる。

それでも復号化に失敗した

上記の内容を何度も確認し、関連するツールなども確認したのに、同じエラーが出続けました。 (今回は、LambdaがJavaで実装されている。)

{
  "errorMessage": "null (Service: AWSKMS; Status Code: 400; Error Code: InvalidCiphertextException; Request ID: xxxxxxxx-1234-5678-xxxx-xxxxxxxxxxxxx)",
  "errorType": "com.amazonaws.services.kms.model.InvalidCiphertextException",

Class InvalidCiphertextException

上記に記載されていた説明によると、

From the ImportKeyMaterial operation, the request was rejected because AWS KMS could not decrypt the encrypted (wrapped) key material. (AWS KMSが暗号化されたキーマテリアルを復号化できなかったため、ImportKeyMaterialオペレーションからリクエストが拒否されました。)

やはり復号化に失敗しているよ、というエラーメッセージ。

バグ発見

AWSコンソールのLmbda関数ページで、ポチポチで環境変数の編集する際、任意のKMSを指定し暗号化し保存。 暗号化した値を復号化すると、復号化に失敗しました。

つまり、AWSコンソールのLambda関数ページで表示されている値は、正しくない値ということ。

裏取り

試しにaws cliで暗号化し、暗号化されたデータをLambdaの環境変数の値にそのまま入力。 プログラムの方で復号化が成功した。

まとめ

Lambda関数ページのUIは大分アップデートされているので、その関係でバグが発生しているようでした。(2020/07時点) たしかに、以前のUIをみてみると、環境変数の編集部分のUIも変更されているようでした。

AWSで明らかに詰まっている場合、cliを使用して裏取りや、describeなどで設定項目などを確認することは改めて必須だと思いました。

以上.

【terraform】"Error: Failed to load state" を解決する?!

今回は、Terraformについてです。

わたしがちょっとしたことでハマってしまったエラーについて、簡単ではありますが、メモがてら残したいと思います。

タイトルに"?!"と書いたのは、決定的な解決策?というか、 そもそも私のTerraformに関しての知見が足りないことでハマってしまったと思うので、ご了承ください。。。

また、完全な対応策というよりは、一時的な対応策になるので、そこもご了承ください。

(※完全にTerraformのstateファイルの挙動を理解していないので、わかり次第更新or新規で記事を投稿します!)

では、さっそく。

まえおき

Terraformでコマンドを叩いていたときのこと。

terraform planterraform applyなどなど

そしたらいきなり以下のエラーメッセージが表示されて、コマンドが叩けなくなってしまった。

Error: Failed to load state: Terraform 0.12.20 does not support state version 4, please update.

エラー内容的に、

Terraformのヴァージョン0.12.20は、stateファイル(.tfstate)のヴァージョン4をサポートしていません。アップデートしてください。

まあ、そのままなんだが、Terraformのヴァージョン0.12.20は、当時tfenvの最新ヴァージョンで、

前回実行したときのstateファイルにも、以下が記述され問題なさそう。

{
  "version": 4,
  "terraform_version": "0.12.20",
  "serial": 11,
.... 以下略 .... 

 調査

tfstateファイルは、手動で変更するのは推奨されてはいないので、手を加えたくありません。

同様に、ファイルを他のディレクトリにも移動させたくはありませんでした。

ググってみたところ、これしか近しいのが見つからず。。

github.com

と、ここで思ったこと。

思い当たる節

ちょっとした検証だったので、stateファイルはローカルで管理していました。

その際、.tfstateファイルをデフォルトの階層ではなく(terraform applyした階層)、.terraformに出力するようにしていました。

terraform {
  backend "local" { path = ".terraform/terraform.tfstate" }
}

.terraformディレクトリは、自動的に作成されるディレクトリなので、なーーんか怪しいかんじがしました。

一時的に対応

先に結論!

.tfstateファイルを移動させ、新たにterraform initする。

.terraformディレクトリから、違うディレクトリにstateファイルを移動させます。

この時、新たにディレクトリ作成してもいいし、backendで指定していたところを削除して、デフォルト状態にしてもいいと思います。

次に、コマンドterraform plan / applyをすると、以下のメッセージが表示されると思います。

Backend reinitialization required. Please run "terraform init".
Reason: Initial configuration of the requested backend "local"

The "backend" is the interface that Terraform uses to store state,
perform operations, etc. If this message is showing up, it means that the
Terraform configuration you're using is using a custom configuration for
the Terraform backend.

Changes to backend configurations require reinitialization. This allows
Terraform to setup the new configuration, copy existing state, etc. This is
only done during "terraform init". Please run that command now then try again.

If the change reason above is incorrect, please verify your configuration
hasn't changed and try again. At this point, no changes to your existing
configuration or state have been made.

Error: Initialization required. Please see the error message above.

tfstateファイルが意図したディレクトリにないので、バックエンドの初期化が必要とのこと。

なので、terraform initしましょうって書いてあります。

initする前に、前回applyを実行したときに反映したリソースを考慮します。

理由は、initコマンドを叩くとわかるのですが、以下を問われるかと思います。

$ terraform init

Initializing modules...

Initializing the backend...
Do you want to copy existing state to the new backend?
  Pre-existing state was found while migrating the previous "local" backend to the
  newly configured "local" backend. No existing state was found in the newly
  configured "local" backend. Do you want to copy this state to the new "local"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: no

Successfully configured the backend "local"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...

Terraform has been successfully initialized!

簡単に訳すと、

設定された新しい"ローカル"バックエンドがあります。 新しく構成された"ローカル"バックエンドに既存の状態が見つかりませんでした。 コピーするには"yes"、空の状態で開始するには"no"を入力。

新しくstateファイルを管理するにあたって、"no"を選択する場合、

(おそらく)前回まで反映したリソースが反映してなかったことになります。

わたしの場合、そこまで重くないリソースを反映していたので、"no"を選択し完全に新規で管理することにしました。

terraform init実行!

イニシャライズ完了すれば一旦オーケーです。

ちょっと気になったこと

stateファイルに関しては、色んな記事で見かけますが、planファイルなるものが存在することも頭の片隅に入れておくべきかと思いました。

  • stateファイル -> terraformのリソースを管理
  • planファイル -> stateファイルを管理

planファイルは、terraform apply実行時に行われる一連の変更の説明や、stateファイルの配置場所を設定しているファイルになるのかと思います。

上記で説明したエラーに関連して、planファイルは.terraform/ディレクトリに自動生成されるようです。

もし、stateファイルをそのディレクトリに出力するようにしていると、ファイル名がおなじならどっちのファイルがどっちのファイルかわからなくなっていた、というわけです。

まとめ

まとめるほど、完全に理解できていないのですが、、、

一旦、.terraformディレクトリにはstateファイルを出力しないようにすることにしました。

ヴァージョン0.12系の記事も思ったよりなかったので、あまり下手なことはせずに管理するのもありかと思います。

もう少しアップデートが進んで、公式ドキュメントも充実してきたら色々とローカルでの管理方法を試してみようと思います。

それまでは、S3で管理したりするのがベターかな。

また、まとめなのに1つ疑問が。。。

私は新たにディレクトリを作成し、backendで指定し管理したのですが、コマンドを(plan)を叩くと成功はするですが、

新しく作成したディレクトリと、なぜか.terraformディレクトリと2つのstateファイルが作成されました。。。

なんなんだこれ。。。

(stateファイルとplanファイルがあると書かれている英語の記事を見つけました。。)

これは後ほど調査してみたいと思います。

あんまりまとまっていない内容でしたが、

以上.

【Python】pyenv installでインストールできなかった話... →解決!!

今回はPythonのヴァージョン管理ツール、pyenvです。

前回の記事同様、環境としてはWindowsのWSL(Ubuntu)でゴニョゴニョしていました。

この記事もtipsのみで、記事内容は短いのであしからず!

まえおき

WindowsのWSL、Ubuntu18.04を使用していました。

Pythonがちょっと必要になったので、定番のpyenvをインストール!

インストール自体は問題なく、いつも通りpyenv install <version> と!

そしたら以下。

curl: (7) Failed to connect to www.python.org port 443: Connection refused
error: failed to download Python-3.7.6.tar.xz

あれーーー、プロキシの設定はしてあるはずなのに、なんでだろう~。。。

この前の記事でも少し紹介しました、WSLでの環境設定でプロキシサーバーがある場合、

ちょっと設定をしてあげる必要があったので、設定はしたはず。

o21o21.hatenablog.jp

ちょっとエラーをみてみる

まあ、それはそうと、まずエラーの確認から。

curl: (7) Failed to connect to www.python.org port 443: Connection refused
error: failed to download Python-3.7.6.tar.xz

叩いたコマンドは、pyenv install 3.7.6 --verbose

--verboseは、インストールするときの詳細を表示してくれるオプションです。

うん、pyenvはcurlを使っているのね。なんか通信が外に出られていないのねってこと。

curlの場合、プロキシ設定として、ホームディレクトリに.curlrcというファイルを作成し、

ファイルを以下のように記述します。

proxy-user = "(user_name):(pwd)"
proxy = "http://proxy.xxx.co.jp:(port)"

では、単純にcurlを叩いてみる。(この前通ることは確認したばかりなのになーー。。。)

結果、やはりcurlはちゃんと外に出られているようです。(レスポンスが返ってきました)

.basrc.bash_profileにもプロキシの設定はしてあります。

ええーーーなんでだーー

解決策

あーだこうだ考えたり、試したり、ググってみたところ、以下のコマンドで通りました。

$  https_proxy=http://proxy.xxx.co.jp:8080 pyenv install 3.7.6

なんか.curlrcに記述してあるproxyより、pyenvがcurlを呼んだときにhttpsが自動的に押し付けられるかんじになるのかな?

ちょっとまだ調べきれてないですが、完全にわかったらまた更新しようと思います。

取り急ぎ、以上

【Terraform】Windows(WSL)に、tfenvをインストール!

今回もWindows系です。

まえおき

Terraformを使用するにあたって、バージョン管理が必要ですね。

そのままインストールしてもいいと思いますが、後々のことを考えたり、

チームメンバーとの環境を合わせるにあたっても、バージョンの管理は必須です。

MacOSの方だと、brewで簡単にインストールできるみたいですが、

Windowsだとそんなに記事がなかったので、ただのインストールのみの記事ですが、メモがてら残しまーす。

今回は、WindowsWSLでインストールしてみようと思います。

WSLについては過去記事に少しあるので、なんか参考になればと思います!

o21o21.hatenablog.jp

o21o21.hatenablog.jp

tfenv

Terraformのバージョン管理は、tfenvが一般的みたいです。

github.com

Githubにあるので、単純にgit cloneしてくるだけです!

導入

まず、ホームディレクトリにクローンします。

$ git clone https://github.com/tfutils/tfenv.git ~/.tfenv

.bash_profileにパスを通します。

export PATH="$HOME/.tfenv/bin:$PATH"

反映もわすれずに。

$ source .bash_profile

確認してみます。

$ tfenv -v

tfenv 2.0.0-alpha3-2-ge36f027

これでおkですね!あっさりインストールできました。

コマンド色々メモ

tfenvの最低限のコマンドをメモします。

# インストールしたバージョンを表示
$ tfenv list

# インストール可能なヴァージョンを表示
$ tfenv list-remote

# ヴァージョンを指定してインストール
$ tfenv install <version>

※ 最初のインストールで、エラーが発生。
WSL(Ubuntu)で、unzipをインストールしてないことが原因でしたので、以下を実行。
$ sudo apt-get unzip

# バージョンの切り替え
$ tfenv use 0.12.20

Switching to v0.12.20
Switching completed

以上.

【Windows】Dokcer + WSL + VSCodeが楽!

昨日に引き続いて、Windowsの開発環境がテーマです!

今回はそんなに内容がありませんが、Windowsでの開発がそんなになかったので

自分のデフォルト的な設定を残しがてら記事を書きます。

WSLからWindows for Dockerを操作

前回の記事で少し詳しい内容を書きました!

o21o21.hatenablog.jp

Linux操作に慣れてる人にとっては、だいぶ良い環境になると思います!

ただ、ヴァージョンアップなど、ある程度自由にできない環境だとちょっと環境設定のときに試行錯誤が必要かもしれません。

↑上記の設定が済んだあと、エディタはどうすればいいのかと思いました。

エディタ

わたしの場合、vimも好きなので、そのままWSLの方でvimの設定を少しすれば使用できるので、

すごく困るわけではないのです。

が、

エディタを使用したデバッグなど、エディタのプラグイン的なので便利に利用できるものも多いはずです。

ここでは、VSCodeを紹介しておきます!

code.visualstudio.com

まだWSL+VSCodeを駆使してがっつり開発している段階ではないですが、すごく楽な拡張機能を見つけたので、残しておきます。

WSLのプロジェクトに接続

WSLからWindowsのDockerを操作できることはよかったので、

今度は、git cloneなどでプロジェクトをクローンしてきたプロジェクトフォルダを簡単に開けないものか。。。

ということで、VSCodeのこのプラグイン

Remote Development !!

拡張機能の検索から、↑で調べます。

インストールしたら、左のメニューの "リモート エクスプローラー" を選択します。

そうすると、"WSL TARGETS" という項目が自動的に表示されています。

接続したので、そのままフォルダを開けば大丈夫です!

いやーーーーー、ほんとに便利です!

ものの1分もかからずにWSLのプロジェクトを開くことができました!!

以上.

marketplace.visualstudio.com