TerraformはAWSなどのIaaS上でインフラを構築、管理するためのツールとしてよく使われてます。
一方、公式プラグインとしてKubernetesのリソースを管理するためのProviderが提供されており、これを使ってKubernetesのリソースを管理すると結構便利だったので紹介します。
kubectlでリソースを直接いじるのに比べると、
-
terraform plan
でDryRunできる - その際、もちろん既存のリソースとの差分を見ることができる
- リソース同士の参照(Docker RegistryのSecretをPodから見るとか)をコード上で表現でき、参照が壊れてると実行前にエラーにできる
- 変数や関数、モジュールを使用して定義を共通化できる
-
terraform destroy
で全部なかったことにできる
あたりがメリットでしょうか。
では、以下Mac上にインストールしたminikube
にローカルのterraformからアクセスするというローカルに閉じた環境で、実際にKubernetesのリソースを管理する様をつらつらと書いていきます。
この記事で使用したterraformのプロジェクトは、以下にPushしているので併せてご参照ください。
minikube
のインストールは超絶簡単なので、以下を参考にインストールしてみていただければと思います。
Kubernetes Providerの設定
terraformからKubernetesのクラスタを設定するために、本来は以下を参考に、apiserverのURLやユーザー名などの認証情報を設定する必要があります。
ただ、minikube
は.kube/config
に認証情報を書き込み、またterraform
のKubernetes Providerはデフォルトで.kube/config
を見るので、minikube
環境にローカルからアクセスする場合は単に宣言だけで大丈夫です。
ここでは、terraform-kubernetes-demo
というディレクトリを作成して、以下のファイルを作成することにします。
provider "kubernetes" {}
terraform init
を実行することでKubernetes Providerがダウンロードされ、kubernetes-provider-demo
ディレクトリに設定されます。
Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "kubernetes" (1.0.0)...
ConfigMapをTerraformで管理する
まず、ConfigMapを管理してみます。現時点のKubernetes Providerだと、このConfigMapとSecretの管理が一番便利に感じるところです。
tfファイルは、以下のようになります。
resource "kubernetes_config_map" "infra" {
metadata {
name = "infra-env"
}
data {
db_host = "dbhost:5432"
cache_host = "cache:6379"
}
}
さて、上記ファイルを適当なファイル名で作成し、terraform plan
でDry Runしてみます。
すると、以下のように作成されようとしているConfigMapが表示されます。
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
+ kubernetes_config_map.infra
id: <computed>
data.%: "2"
data.cache_host: "cache:6379"
data.db_host: "dbhost:5432"
metadata.#: "1"
metadata.0.generation: <computed>
metadata.0.name: "infra-env"
metadata.0.namespace: "default"
metadata.0.resource_version: <computed>
metadata.0.self_link: <computed>
metadata.0.uid: <computed>
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
実際に作成する前に内容を確認できるのがいいですね。
terraform apply
とすると、実際にkubernetesクラスタにこのConfigMapが作成されます。
terraform apply
# kubernetes_config_map.infra: Creating...
# data.%: "" => "2"
# data.cache_host: "" => "cache:6379"
# data.db_host: "" => "dbhost:5432"
# metadata.#: "" => "1"
# metadata.0.generation: "" => "<computed>"
# metadata.0.name: "" => "infra-env"
# metadata.0.namespace: "" => "default"
# metadata.0.resource_version: "" => "<computed>"
# metadata.0.self_link: "" => "<computed>"
# metadata.0.uid: "" => "<computed>"
# kubernetes_config_map.infra: Creation complete after # 0s (ID: default/infra-env)
# Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
kubectl describe cm infra-env
# Name: infra-env
# Namespace: default
# Labels: <none>
# Annotations: <none>
# Data
# ====
# cache_host:
# ----
# cache:6379
# db_host:
# ----
# dbhost:5432
# Events: <none>
さらに、以下のようにConfigMapを変更してみます。
resource "kubernetes_config_map" "infra" {
metadata {
name = "infra-env"
}
data {
db_host = "dbhost2:5432" # 変更する
cache_host = "cache:6379"
}
}
ここでterraform plan
を行うと、AWS Providerのような他Provider同様、差分が表示されます。
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
~ kubernetes_config_map.infra
data.db_host: "dbhost:5432" => "dbhost2:5432"
Plan: 0 to add, 1 to change, 0 to destroy.
------------------------------------------------------------------------
このように、実際に変更される前に、どのようにConfigMapが変更されるのか確認できます。
差分OKであれば、 terraform apply
で差分を適用します。
terraform apply
# kubernetes_config_map.infra: Refreshing state... (ID: default/infra-env)
# kubernetes_config_map.infra: Modifying... (ID: default/infra-env)
# data.db_host: "dbhost:5432" => "dbhost2:5432"
# kubernetes_config_map.infra: Modifications complete # after 0s (ID: default/infra-env)
SecretをTerraformで管理する
ConfigMap同様、Secretもterraformで管理できます。kubectlで作るのに比べてbase64エンコードもしてくれたりで直感的にSecretを作成できます。
まず、tfファイルを作成します。
resource "kubernetes_secret" "basic_auth" {
metadata {
name = "basic-auth"
}
data {
username = "admin"
password = "Admin"
}
type = "kubernetes.io/basic-auth"
}
terraform apply
を実行すると、上記内容でSecretが作られます。base64でエンコードする必要もありません。
kubernetes_secret.basic_auth: Creating...
data.%: "" => "2"
data.password: "<sensitive>" => "<sensitive>"
data.username: "<sensitive>" => "<sensitive>"
metadata.#: "" => "1"
metadata.0.generation: "" => "<computed>"
metadata.0.name: "" => "basic-auth"
metadata.0.namespace: "" => "default"
metadata.0.resource_version: "" => "<computed>"
metadata.0.self_link: "" => "<computed>"
metadata.0.uid: "" => "<computed>"
type: "" => "kubernetes.io/basic-auth"
kubernetes_secret.basic_auth: Creation complete after 0s (ID: default/basic-auth)
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
では、少しこのtfファイルを変更してみます。ついでに、変数も使ってみます。
variable "basicPassword" {
}
resource "kubernetes_secret" "basic_auth" {
metadata {
name = "basic-auth"
}
data {
username = "admin"
password = "${var.basicPassword}"
}
type = "kubernetes.io/basic-auth"
}
TF_VAR_basicPassword=aaa terraform plan
# An execution plan has been generated and is shown below.
# Resource actions are indicated with the following symbols:
# ~ update in-place
# Terraform will perform the following actions:
# ~ kubernetes_secret.basic_auth
# data.password: <sensitive> => <sensitive> (attribute changed)
# Plan: 0 to add, 1 to change, 0 to destroy.
このように、terraformであれば変数や参照、関数が利用できるので、構成を共有するのが楽そうですね。
Kubernetes ProviderのSecretリソースは、ファイルやテンプレートからSecretを作成することもできるので、Docker Registryの認証情報をKubernetesに設定するときなどに便利です。
後片付け
terraform destroy
で、上記で作成したリソースを全て削除できます。
terraform destroy
# kubernetes_config_map.infra: Refreshing state... (ID: default/infra-env)
# kubernetes_secret.basic_auth: Refreshing state... (ID: default/basic-auth)
# An execution plan has been generated and is shown below.
# Resource actions are indicated with the following symbols:
# - destroy
# Terraform will perform the following actions:
# - kubernetes_config_map.infra
# - kubernetes_secret.basic_auth
# Plan: 0 to add, 0 to change, 2 to destroy.
# Do you really want to destroy?
# Terraform will destroy all your managed infrastructure, as shown above.
# There is no undo. Only 'yes' will be accepted to confirm.
# Enter a value: yes
# kubernetes_config_map.infra: Destroying... (ID: default/infra-env)
# kubernetes_secret.basic_auth: Destroying... (ID: default/basic-auth)
# kubernetes_config_map.infra: Destruction complete after 0s
# kubernetes_secret.basic_auth: Destruction complete after 0s
# Destroy complete! Resources: 2 destroyed.
まとめ
Kubernetes Providerでは、その他にもServiceやPod、NamespaceやPVCなど、様々なリソースを管理できます(現時点ではPod
はあってもDeployment
がないのが痛い)。
terraform
は差分が発生したことをコマンドのexit codeで知ることができたり、べき等性のあるコマンドでリソースを管理できたりとCIに組み込むのにとても便利な作りなので、インフラをJenkinsなどで管理しているのであれば一度Kubernetes Providerを試してみてはいかがでしょうか。