2023年1月26日木曜日

pocoで k8s の context を切り替えてみる

 

.bashrc などに下記を記述

function k8c()
{
    local env=$(kubectl config view | egrep '^- context:' -A4 | awk '($0~/name:/){print $2}' | sort | peco)
    kubectl config use-context $env
}


ターミナルにk8cと入力してENTERすると context がメニュー表示されるので、選択すると切り替わります。

starshipなど使ってプロンプトに contextを表示すると便利です。(下記URL参照)


2023年1月24日火曜日

Docker Desktop(k8s)+Localstackでargocdを試す環境をterraformで作ってみた

 

やりたかったこと

  • DokerDesktop+Localstackの環境でk8sを試したい。
  • 試したいk8sパッケージ
    • eso
    • metric server
    • ingress nginx
    • argocd
    • kubernetes dashboard
  • argocd はBitbucketと連携させてnginxをdeploy
  • LocalstackのSSM ParameterStoreに、Bitbuket接続に使用するSSH秘密鍵を登録し、esoでk8sのsecretとして参照できるようにしたい。
  • ingressを使って、argocd, dashboardのGUIを見たい。
  • metric serverのhpaでpodをスケールアウトしたい。
  • 個人の学習目的なので、セキュリティはゆるくていい。


私の環境

  • SparkyLinux6.5(Debian系)
    • ssh秘密鍵(レポジトリアクセス用)
  • k8s
    • DockerDesktop4.12.0
    • kubectl1.25.4
    • helm3.10.2
  • aws
    • localstack1.3.1.dev
    • aws-cli2.9.4
  • terraform
    • tfenv3.0.0
    • tflint0.43.0
    • terraform1.3.6


サンプルコード


https://github.com/blue21jp/aws-sample-terraform-k8s


構成


├── Makefile
├── README.md
├── app/
│   └── deployment.yml
├── demo_todo_k8s.org
├── global/
│   ├── backend.tf
│   ├── ip.sh
│   ├── locals.tf
│   ├── providers_aws.tf
│   ├── providers_localstack.tf
│   └── versions.tf
├── stacks_k8s/
│   ├── 00_check/
│   │   ├── Makefile
│   │   └── outputs.tf
│   ├── 01_aws_ssm/
│   │   ├── Makefile
│   │   └── main.tf
│   ├── 10_k8s_eso/
│   │   ├── Makefile
│   │   ├── k8s_cluster_secret_store.yaml
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 10_k8s_ingress_nginx/
│   │   ├── Makefile
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 10_k8s_metric_server/
│   │   ├── Makefile
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 20_k8s_argocd/
│   │   ├── Makefile
│   │   ├── k8s_argocd_external_secret.yaml
│   │   ├── k8s_repo.yaml
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   ├── repo.tf
│   │   └── versions.tf
│   ├── 20_k8s_dashboard/
│   │   ├── Makefile
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 40_app_argocd/
│   │   ├── Makefile
│   │   ├── k8s_app.yaml
│   │   ├── k8s_hpa.yaml
│   │   ├── k8s_ingress.yaml
│   │   ├── k8s_service.yaml
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── Makefile
│   ├── locals_all.tf
│   └── locals_dev.tf
└── stacks_template/
    ├── 00_check/
    │   ├── Makefile
    │   └── outputs.tf
    ├── Makefile
    ├── locals_all.tf
    ├── locals_dev.tf
    ├── locals_prd.tf
    └── locals_stg.tf
こんなイメージ



この構成の説明と基本操作方法は、別記事の「awsとlocalstackを切り替えながらterraformを使いたい」を参照。
app/ には、argocdでapp(nginx)をdeployするためのmanifestを置いてます。


構築


準備


Bitbucket
レポジトリアクセス用のSSH秘密鍵は下記のPATHを使用します。
~/.ssh/id_rsa

awscli 
Localstack用のprofile名は "localstack" を使用します。

/etc/hosts
下記のホスト名を登録します。ingressに設定してGUIアクセスで使用します。
127.0.0.1 argocd.example.local
127.0.0.1 nginx.example.local
127.0.0.1 dashboard.example.local

Terraform実行


下記コマンドを実行すると、terraform applyが実行されます。
これで、Localstack+DockerDesktop環境にリソース一式(ssm, argocd, dashbord, etc)が構築されます。
$ make apply OPT="-auto-approve" -C stacks_k8s


確認


argocdのGUI
http://argocd.example.local
Userは、adminです。
Passwordは下記コマンドで調べます。
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath=“{.data.password}” | base64 -d; echo

dashbordのGUI
http://dashboard.example.local
認証を無効に設定しています。
認証画面で[スキップ]ボタンをクリックすると入れます。

app(nginx)のページ
http://nginx.example.local
nginxの welcome ページが表示されます。


破棄


argocdでdeployしたnginxを削除します。
$ kubectl delete deploy nginx-deploy

下記コマンドを実行するとterraform destroyが実行されます。
を実行し、リソースを全部、破棄します。
$ make destroy OPT="-auto-approve" -C stacks_k8s


おまけ


demo_todo_k8s.org に記載した手順で構築と動作確認を実施している様子を動画にしました。


この動画で実行しているコマンド(aws-cliのalias)については、下記の記事を参照














2023年1月21日土曜日

pecoでecsexecしてみる


ecsexec については、下記URL参照。


peco でECSタスクをメニュー表示して選択し、ecsexec してコンテナに入れるようにします。


下記を ~/.bashrc などに記述します。

ecsexec() {
  if [ $# -eq 0 ]; then
    echo "usage: ecsexec <cluster name>"
    return
  fi

  local cluster=$1
  local tasks=$(aws ecs list-tasks --cluster $cluster --query 'taskArns[]' --output text | tr "\t" " ")
  local w_task=$(aws ecs describe-tasks \
      --cluster $cluster \
      --tasks $tasks \
      --output json \
      |jq -r '.tasks[]|{group:.group,name:.containers[].name,runtimeId:.containers[].runtimeId}' \
      | jq -r -s 'map(map(.)) as $rows|$rows[]|@csv' \
      | sort \
      | peco)
  local svc=$(echo $w_task| awk -F, '{print $1}'| cut -d':' -f2| tr -d '"')
  local task=$(echo $w_task| awk -F, '{print $3}'| cut -d'-' -f1| tr -d '"')
  local container=$(echo $w_task| awk -F, '{print $2}'| tr -d '"')
  echo "*************************************************"
  echo "cluster  : $cluster"
  echo "service  : $svc"
  echo "task     : $task"
  echo "container: $container"
  echo "*************************************************"

  aws ecs execute-command \
  --cluster $cluster \
  --task $task \
  --container $container \
  --interactive --command "/bin/sh"
}


ターミナルで "ecsexec <クラスタ名>" と入力して実行すると、下図のようにECSタスクが表示されるので選択します。

メニューには、「サービス名」、「コンテナ名」、「ECSタスクのruntimeId(task-id含む)」が表示されます。




ecsexecが成功してコンテナに入ると、下図のように表示されます。





2023年1月15日日曜日

環境(awsとlocalstack)を切り替えながらterraformを使ってみた


私がterraformでやりたかったこと

  • 環境(awsとlocalstack)を切り替えながらterraformを使いたい
  • 寝る前にAWSリソース破棄して、翌日、再構築したい(節約のため)
  • 個人の学習目的なので、terraformのbackendはlocalでいい
  • 自作moduleは、好きではないが、たまに作るかもしれない
  • 環境ごとにディレクトリを作りたくない
  • 環境切り替えにwokspaceは使いたくない
  • 環境差分は変数にして、awsとlocalstackで同一コードを実行したい
  • localstack停止後はリソース消えるので、terraformも初期状態にリセットしたい


私の環境

  • SparkyLinux6.5(debian系)
  • terraform1.3.6
  • tfenv3.0.0
  • tflint0.43.0
  • awscli2.9.4
  • localstack1.3.1.dev
  • make4.3
  • aws ec2キーペア(sandbox)


サンプルコード


https://github.com/blue21jp/aws-sample-terraform


注意)

サンプルコードのEC2はキーペア(sandbox)を使用します。

このキーペアは、terraformで作成しないので、事前に用意するか、コードを修正してください。


構成


コードの構成は下記のとおり。
terraformコマンドは、Makefileに記述して実行します。
makeの使用方法については後述。
.
├── Makefile
├── README.md
├── global/
│   ├── backend.tf
│   ├── ip.sh
│   ├── locals.tf
│   ├── providers_aws.tf
│   ├── providers_localstack.tf
│   └── versions.tf
├── modules/
│   ├── ec2-spot/
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   └── ecs-fargate/
│       ├── cwl.tf
│       ├── iam.tf
│       ├── main.tf
│       └── variables.tf
├── stacks_base/
│   ├── 00_check/
│   │   ├── Makefile
│   │   └── outputs.tf
│   ├── 01_network/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── main.tf
│   │   └── versions.tf
│   ├── 02_ec2_nat/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── locals.tf
│   │   └── main.tf
│   ├── Makefile
│   ├── locals_all.tf
│   ├── locals_dev.tf
│   └── locals_prd.tf
├── stacks_demo/
│   ├── 00_check/
│   │   ├── Makefile
│   │   └── outputs.tf
│   ├── 03_ec2/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── locals.tf
│   │   ├── locals.tf.dev
│   │   ├── locals.tf.prd
│   │   └── main.tf
│   ├── 04_ecs/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── locals.tf
│   │   ├── locals.tf.dev
│   │   ├── locals.tf.prd
│   │   ├── main.tf
│   │   ├── taskdef_amzn2.json
│   │   └── taskdef_nginx.json
│   ├── Makefile
│   ├── locals_all.tf
│   ├── locals_dev.tf
│   └── locals_prd.tf
└── stacks_template/
    ├── 00_check/
    │   ├── Makefile
    │   └── outputs.tf
    ├── Makefile
    ├── locals_all.tf
    ├── locals_dev.tf
    ├── locals_prd.tf
    └── locals_stg.tf

こんなイメージ


リソース構築用のterraformコードの格納場所

modules/

  • 自作のモジュールは、modules/配下にディレクトリを作成して、そこに置きます。

stacks_xxxx/

  • 構築するリソース(vpc,ec2,etc)は、共通用、デモ用などグループ化してstacks_xxxx/ ディレクトリを作成し、そこに置きます。

stacks_xxxx/NN_xxxxx

  • stacks_xxxx/ 配下は、「数値で始まるディレクトリ」を作成して、そこにコードを格納します。この「数値で始まるディレクトリ(00_check,01_netowprk,etc)」を、ここではスタックと呼ぶことにします。
  • スタックは、ライフサイクルが同じリソースの集まりです。
  • スタックの数値の小さいものから構築すると stacks_xxxx が完成するようにします。
  • 全環境で、同一コード(スタックのコード)を実行します。

環境差分の変数を設定する場所

global/

全環境の全スタックで参照できます。

  • locals.tf・・・local.global.XXXXで参照する

stacks_xxxx/

たとえば、stacks_baseの下記ファイルに定義した変数は、stacks_base配下のスタックだけで参照できます。

  • locals_all.tf・・・全環境共通の変数。local.common_all.XXXXで参照する
  • locals_dev.tf・・・dev環境用の変数。local.common_env.XXXXで参照する
  • locals_stg.tf・・・stg環境用の変数。local.common_env.XXXXで参照する
  • lcoals_prd.tf・・・prd環境用の変数。local.common_env.XXXXで参照する
 

stacks_xxxd/NN_xxxx

たとえば、00_chackの下記ファイルに定義した変数は、00_checkだけで参照できます。

  • locals.tf.dev・・・dev環境用の変数。local.XXXXで参照する
  • locals.tf.stg・・・stg環境用の変数。local.XXXXで参照する
  • locals.tf.prd・・・prd環境用の変数。local.XXXXで参照する

terraformプラグインのキャッシュ場所

awsなどのプラグインは、「terraform init」時にダウンロードして、下記にキャッシュします。

  • ${HOME}/.teraform.d/plugin-cache

tfstateの格納場所

terraformのstateは、スタック用ディレクトリ(00_check, 01_network, etc)内に、環境ごとに作成します。

  • stacks_xxxx/NN_xxxx/tfstate.d/dev
  • stacks_xxxx/NN_xxxx/tfstate.d/stg
  • stacks_xxxx/NN_xxxx/tfstate.d/prd

プロビジョニング環境

構築する環境は3種類の前提

  • dev・・・ localstack
  • stg・・・ awsアカウント ※サンプルコードでは未使用
  • prd・・・ awsアカウント


プロビジョニング先の環境を指定する方法

locals_dev.tf, locales_stg.tf, locals_prd.tf でプロビジョニングする環境を指定します。

下記のようにして、awscliのプロファイル名と、リージョンを設定します。
env_typeは、環境を識別するための値(dev|stg|prd)を設定します。

locals {
  common_env = {
    env_type = "dev"
    profile  = "localstack"
    region   = "us-east-1"
  }
}

localstackで使用するサービスを設定する方法

global/provisers_localstack.tf で設定します。

下記のようにして使用するサービスのエンドポイントをlocalstackに向けます。

  endpoints {
    sts            = "http://${data.external.myip.result["ip"]}:4566"
    s3             = "http://${data.external.myip.result["ip"]}:4566"
    ec2            = "http://${data.external.myip.result["ip"]}:4566"
    route53        = "http://${data.external.myip.result["ip"]}:4566"
    cloudwatch     = "http://${data.external.myip.result["ip"]}:4566"
    iam            = "http://${data.external.myip.result["ip"]}:4566"
    eks            = "http://${data.external.myip.result["ip"]}:4566"
    wafregional    = "http://${data.external.myip.result["ip"]}:4566"
    wafv2          = "http://${data.external.myip.result["ip"]}:4566"
    waf            = "http://${data.external.myip.result["ip"]}:4566"
    cloudfront     = "http://${data.external.myip.result["ip"]}:4566"
    lambda         = "http://${data.external.myip.result["ip"]}:4566"
    secretsmanager = "http://${data.external.myip.result["ip"]}:4566"
    cloudformation = "http://${data.external.myip.result["ip"]}:4566"
    ssm            = "http://${data.external.myip.result["ip"]}:4566"
  }


使い方

terraformコマンドは、makeで実行します。

ここでは、特に記載がなければ、TOPディレクトリでmakeコマンドを実行します。

動作環境の確認

stacks_xxxx/00_check を使用します。このスタックは動作環境の情報を表示するだけでリソースは何もつくりません。

dev(localstack)に向ける場合

これで terraformの init, tflint, planが実行されます。

$ make plan -C stacks_base/00_check
実行前の00_checkは下記のとおり
Permissions Size User   Date Modified Name
.rw-r--r--     6 blue21 14 Jan 16:23  .terraform-version
.rw-r--r--  2.6k blue21 14 Jan 16:23  Makefile
.rw-r--r--   246 blue21 14 Jan 16:23  outputs.tf

実行後の00_checkは下記のようになります。

アンダースコアで始まるシンボリックリンク・ディレクトリは make で自動生成したものです。

Permissions Size User   Date Modified Name
drwxr-xr-x     - blue21 14 Jan 19:04  .terraform
.rw-r--r--     6 blue21 14 Jan 16:23  .terraform-version
.rw-r--r--   464 blue21 14 Jan 19:04  .terraform.lock.hcl
lrwxrwxrwx    23 blue21 14 Jan 19:04  _backend.tf -> ../../global/backend.tf
lrwxrwxrwx    16 blue21 14 Jan 19:04  _locals_all.tf -> ../locals_all.tf
lrwxrwxrwx    16 blue21 14 Jan 19:04  _locals_env.tf -> ../locals_dev.tf
lrwxrwxrwx    22 blue21 14 Jan 19:04  _locals_global.tf -> ../../global/locals.tf
lrwxrwxrwx    36 blue21 14 Jan 19:04  _providers.tf -> ../../global/providers_localstack.tf
drwxr-xr-x     - blue21 14 Jan 19:04  _tfstate.d
lrwxrwxrwx    24 blue21 14 Jan 19:04  _versions.tf -> ../../global/versions.tf
.rw-r--r--  2.6k blue21 14 Jan 16:23  Makefile
.rw-r--r--   246 blue21 14 Jan 16:23  outputs.tf

prd(aws)に向ける場合

ENVで環境を指定します。(dev|stg|prd)

$ make plan ENV=prd -C stacks_base/00_check
シンボリックリンク先は prd 用に変わります。
ermissions Size User   Date Modified Name
drwxr-xr-x     - blue21 14 Jan 19:07  .terraform
.rw-r--r--     6 blue21 14 Jan 16:23  .terraform-version
.rw-r--r--   464 blue21 14 Jan 19:04  .terraform.lock.hcl
lrwxrwxrwx    23 blue21 14 Jan 19:07  _backend.tf -> ../../global/backend.tf
lrwxrwxrwx    16 blue21 14 Jan 19:07  _locals_all.tf -> ../locals_all.tf
lrwxrwxrwx    16 blue21 14 Jan 19:07  _locals_env.tf -> ../locals_prd.tf
lrwxrwxrwx    22 blue21 14 Jan 19:07  _locals_global.tf -> ../../global/locals.tf
lrwxrwxrwx    29 blue21 14 Jan 19:07  _providers.tf -> ../../global/providers_aws.tf
drwxr-xr-x     - blue21 14 Jan 19:07  _tfstate.d
lrwxrwxrwx    24 blue21 14 Jan 19:07  _versions.tf -> ../../global/versions.tf
.rw-r--r--  2.6k blue21 14 Jan 16:23  Makefile
.rw-r--r--   246 blue21 14 Jan 16:23  outputs.tf

スタックのapply

例として、stacks_base/01_network を使用します。

このスタックはVPC,Subnetを作成します。

dev(localstack)に向ける場合

$ make apply -C stacks_base/01_network

prd(aws)に向ける場合

$ make apply ENV=prd -C stacks_base/01_network

ちなみに、terraform apply に引数を追加したい場合は下記のようにします。

$ make apply ENV=prd OPT="-auto-approve" -C stacks_base/01_network

また、stacks_baseのスタックを一括でapplyしたい場合は以下のようにします。

$ make apply ENV=prd OPT="-auto-approve" -C stacks_base


スタックのdesttroy

例として、stacks_base/01_network を使用します。

使用方法は apply と同じです。

dev(localstack)に向ける場合

$ make destroy -C stacks_base/01_network

prd(aws)に向ける場合

$ make destroy ENV=prd -C stacks_base/01_network


初期化

localstack, awsのリソースを全部destroyしたあとに、下記を実行すると、tfstateやmakeが自動生成したシンボリックリンクを削除して初期状態に戻します。

$ make clean ENV=prd -C stacks_base/01_network


その他

  • make list -C stacks_xxxx/NN_xxxx
    tarraform state list を実行します。

  • make outputs -C stacks_xxxx/NN_xxxx
    terraform output を実行します。

  • make mv OPT="xxxx yyyy" -C stacks_xxxx/NN_xxxx
    terraform state mv $OPT を実行します。

  • make rm OPT="xxx" -C stacks_xxxx/NN_xxxx
    terraform state rm $OPT を実行します。

  • make import OPT="xxx yyyy" -C stacks_xxxx/NN_xxxx
    terrafprm import $OPT を実行します。


おまけ

サンプルコードを使って、demo_todo.orgの手順で実施した構築作業を動画にしました。


この動画で実行しているコマンド(aws-cliのalias)については、下記の記事を参照







2023年1月8日日曜日

pecoでawscliのprofileを切り替える


peco は、「brew install peco」などとするとインストールできます。


~/.bashrcなどに下記を記述します。

alias awsa='aws sts get-caller-identity'

export AWS_PROFILE='sandbox'
function awsp()
{
    export AWS_PROFILE=$(egrep '^\[profile' ~/.aws/config | cut -d" " -f2 | tr -d ']' | peco)
}


ターミナルで"awsp"と入力して実行すると、下図のように awscliのprofileを選択するメニューが表示されるので、profileを選択すると環境変数のAWS_PROFILEに選択したprofileが設定されます。


starshipなど使用してターミナルのプロンプトにAWS_PROFILEを表示するようにしておくと便利です。


また、ターミナルで"awsa"と入力して実行すると、アカウントIDを確認できます。