2023年2月26日日曜日

ログイン画面を通らずにAWSコンソールをコマンド一撃で開いてみる


私のPC環境

- SparkyLinux6.5

- aws-cli2.x

- jq


私のAWS環境

- AWSアカウントが2つあります。

- 認証用と検証用です。

 

私がAWSコンソールを使用するときは、サインインするときにMFAの認証コードを入力しています。

また、認証用アカウントにサインインしてから検証用アカウントにスイッチロールする手順にしています。


ちょっと見たいだけのときは、これがめんどくさいので、コマンド一撃で検証用アカウントのAWSコンソールを開くようにしました。

下記URLの情報を参考にしています。


下記のコードを ~/awsc_open.sh のPATHで保存します。

ROLE には、スイッチロールで使用するIAM Role名を設定します。

AUTH_PROFILE には、認証アカウントのprofile名(aws-cli)を設定します。

#!/bin/bash

AWS_FED_URL=https://signin.aws.amazon.com/federation
AWS_CONSOLE_URL=https://console.aws.amazon.com/
ROLE=<IamRole>
AUTH_PROFILE=<prfoile>

function urlencode
{
    echo $1 | jq -Rr '@uri'
}


arn=$(aws iam list-roles \
    --query "Roles[?RoleName == '${ROLE}'].Arn" \
    --output text)

if [ "${arn}" == "" ]; then
    echo "${ROLE} is not found."
    exit 1
fi

key=$(aws sts assume-role \
    --profile ${AUTH_PROFILE} \
    --role-arn "${arn}" \
    --role-session-name OneTimeSession \
    --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
    --output text)

access_key=$(echo "${key}" | awk -F"\t" '{printf("%s",$1)}')
secret_access_key=$(echo "${key}" | awk -F"\t" '{printf("%s",$2)}')
session_token=$(echo "${key}" | awk -F"\t" '{printf("%s",$3)}')

if [ "${access_key}" == "" ]; then
    echo "assume-role failed."
    exit 1
fi

json="{\"sessionId\":\"${access_key}\",\"sessionKey\":\"${secret_access_key}\",\"sessionToken\":\"${session_token}\"}"

token=$(curl -s "${AWS_FED_URL}?Action=getSigninToken&Session=$(urlencode ${json})" \
    | jq -r .SigninToken)

if [ "${token}" == "" ]; then
    echo "get signin token failed."
    exit 1
fi

url="${AWS_FED_URL}?Action=login&Issuer=&Destination=$(urlencode ${AWS_CONSOLE_URL})&SigninToken=$(urlencode ${token})"

#echo ${url}
google-chrome --incognito ${url}

exit 0

このファイルを bash aliasに登録します。

~/.bashrc などに下記のように記載します。

alias awsc='~/awsc_open.sh'


ターミナルで awsc と入力してENTERすると、

下図のようなかんじでAWSコンソールを開けます。

ログイン画面は通らずに、いきなりホーム画面にいけます。



環境変数のAWS_PROFILEに設定したAWSアカウントのAWSコンソールが開きます。

Chromeのシークレットモードで開きます。

セッションの有効期限は1時間です。



2023年2月23日木曜日

EKS(fargate)でargocdを試す環境をCloudformationで作ってみた

 

下記の別記事で書いた、terraformで構築したEKS環境をCloudformationで構築してみました。

ただ、k8sの設定は、Cloudformationで出来ないので、kubectl, helmなどのコマンドを使用しています。


私の環境
  • SparkyLinux6.5(Debian系)
  • Bitbucket
    • ssh秘密鍵(レポジトリアクセス用)
  • k8s
    • kubectl1.25.4
    • helm3.10.2
  • aws
    • aws-cli2.9.4
    • eksctl0.13.0
    • rain1.3.0
    • cfn-lint0.73.2
    • ssh秘密鍵(EC2用キーペア)
  • os command
    • make
    • bash
    • jq
    • envsubst

サンプルコード


https://github.com/blue21jp/aws-sample-cfn-eks


構成


.
├── README.md
├── demo_todo.org
├── global/
│   └── variables.mk
├── stacks_base/
│   ├── 01_network/
│   │   ├── Makefile
│   │   └── cfn_vpc.yml
│   ├── 02_prefix_list/
│   │   ├── Makefile
│   │   └── cfn_prefix_list.yml
│   ├── 03_nat/
│   │   ├── Makefile
│   │   └── cfn_nat.yml
│   ├── Makefile
│   ├── variables_all.mk
│   └── variables_prd.mk
└── stacks_eks/
    ├── 01_vpc/
    │   └── Makefile
    ├── 02_ssm/
    │   └── Makefile
    ├── 10_eks_cluster/
    │   ├── Makefile
    │   ├── cfn_eks_cluster.yml
    │   ├── cfn_eks_fargate_profile.yml
    │   └── cfn_eks_oidc.yml
    ├── 11_k8s_init/
    │   └── Makefile
    ├── 20_k8s_alb_controller/
    │   ├── Makefile
    │   └── aws_alb_policy.json
    ├── 20_k8s_eso/
    │   ├── Makefile
    │   ├── aws_eso_policy.json
    │   └── k8s_eso_cluster_secret.yml
    ├── 20_k8s_metric_server/
    │   └── Makefile
    ├── 21_k8s_argocd/
    │   ├── Makefile
    │   └── k8s_argocd_ingress.yml
    ├── 21_k8s_dashboard/
    │   ├── Makefile
    │   └── k8s_dashboard_ingress.yml
    ├── 40_app_argocd/
    │   ├── Makefile
    │   ├── argocd_apps.json
    │   ├── argocd_apps.sh
    │   ├── argocd_git_repositorys.json
    │   ├── argocd_git_repositorys.sh
    │   ├── k8s_argocd_app.yml
    │   ├── k8s_argocd_repo.yml
    │   ├── k8s_external_secret.yaml
    │   └── k8s_ingress_app.yml
    ├── Makefile
    ├── variables_all.mk
    └── variables_prd.mk

この構成の説明と基本操作方法は、下記の別記事を参照。
下記の記事はterraform用なので、多少、本記事のCloudformation用とは使用方法(オプションとか)が異なりますが、考え方は同じです。
今回のEKS環境は、前述の別記事(terraform版)と比較して、下記を変えてます。
  • appは、tf-sample-eks レポジトリを使用します。
  • SecurityGrpoupの設定に、マネージドプレフィックスリストを使用しています。
  • argocd画面のexecを有効にしています。(GUIからpodに入れる)
  • argocd用の設定情報(レポジトリ、アプリケーション)は、40_app_argocdのjsonファイルに記述しています。


構築


準備


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

awscli 
AWS用のprofile名は "sandbox" を使用します。us-east-1で動作確認しています。

ec2キーペア
NATインスタンスで使用するキーペアです。"sandbox"を使用します。
節約のためにNATゲートウェイでなくNATインスタンスを使ってます。

Cloudformation実行


下記コマンドを実行すると、rain deployやawscli,kubeclt,helm,eksctlが実行されます。
これで、AWS環境にリソース一式(vpc, eks, ssm, argocd, dashbord, etc)が構築されます。
$ make -C stacks_base deploy
$ make -C stacks_eks deploy


破棄


下記コマンドを実行するとリソースを全部、破棄します。
$ make -C stacks_eks remove
$ make -C stacks_base remove







2023年2月19日日曜日

Linuxデスクトップで画面操作を録画して編集するときに使ってるツール

 

こんなかんじで、録画した画面操作をGIFアニメーションにしてブログに貼り付けることができます。


私のPC環境は SparkyLinux(Debian系)です。

私が録画と映像編集に使用しているツールは以下です。

上の画像も、これで作成しました。


■録画

vokoscreenNG


■映像編集

shutcut




2023年2月18日土曜日

fig は aws-cli のオプション(S3バケット名など)も補完してくれる


fig については下記URL参照


fig はコマンドの補完などしてくれる、超便利なツールです。

aws-cli も補完してくれますが、AWS_PROFILEを認識してAWSを参照し、バケット名なども補完してくれます。







2023年2月12日日曜日

pecoとrainでCloudFormationのスタックを削除してみる


rain については、下記URLを参照


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

 

rmstack() {
  local stack=$(aws cloudformation describe-stacks \
  --query "Stacks[?contains(StackName,\`$1\`)].[StackName,StackStatus,Description]" \
  --output text | peco | cut -f1)
  rain rm $stack
}

こんなかんじで使います。







2023年2月6日月曜日

よく使うaws-cliは bash のalias とか function にしている

 

aws-cliを、~/.bashrcとか~/.bash_aliases などに書いて使ってます。

--profile は指定せず、環境変数(AWS_PROFILE)でプロファイルを切り替えて使ってます。


EC2関連


# instance
lsec2() {
  local filter=""
  if [ "$1" == "" ]; then
    aws ec2 describe-instances \
    --query 'Reservations[].Instances[].{name:Tags[?Key==`Name`]|[0].Value,instanceId:InstanceId,privateIp:PrivateIpAddress,publicIp:PublicIpAddress,image:ImageId,state:State.Name,sg:SecurityGroups[].GroupName|sort(@)|join(`,`,@)}' \
    --output table
  else
    aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=$1" \
    --query 'sort_by(Reservations[].Instances[].{name:Tags[?Key==`Name`]|[0].Value,instanceId:InstanceId,privateIp:PrivateIpAddress,publicIp:PublicIpAddress,image:ImageId,state:State.Name,sg:SecurityGroups[].GroupName|sort(@)|join(`,`,@)},&name)' \
    --output table
  fi
}

# tag
lsec2-tag() {
  if [ "$1" == "" ]; then
    echo "lsec2-tag <resource-id>"
    return
  fi
  aws ec2 describe-tags --filters "Name=resource-id,Values=$1" --output table
}

# security group
lssg() {
  local key='*'
  if [ "$1" != "" ]; then
    key=$1
  fi
  aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=$key" \
  --query 'sort_by(SecurityGroups[].{id:GroupId, name:GroupName, vpc:VpcId, desc:Description},&name)' \
  --output table
}
lssg-rule() {
  if [ "$1" == "" ]; then
    echo "lssg-rule <security-group-id>"
    return
  fi
  local key="$1"
  aws ec2 describe-security-group-rules \
  --filters "Name=group-id,Values=$key" \
  --output table
}

# elb
alias lselb="aws elbv2 describe-load-balancers --query 'LoadBalancers[].{schme:Scheme,dns:DNSName,state:State.Code}' --output table"

lselb-tg() {
  local cond=""
  if [ "$1" != "" ]; then
    cond=$(printf '?contains(TargetGroupName,`%s`)' $1)
  fi
  aws elbv2 describe-target-groups \
  --query "TargetGroups[$cond].[TargetGroupArn,TargetGroupName]" \
  --output table
}
lselb-health() {
  while read key
  do
    state=$(aws elbv2 describe-target-health \
    --target-group-arn "$key" \
    --query 'TargetHealthDescriptions[].[TargetHealth.State]' \
    --output text)
    echo "$key $state"
  done< <(aws elbv2 describe-target-groups --query "TargetGroups[].[TargetGroupArn]" --output text)
}

# ami
rmami() {
  local ami_ids=$@

  for ami_id in $ami_ids;do
    snapshot_ids=`aws ec2 describe-images --image-ids=$ami_id \
    --query "Images[].BlockDeviceMappings[].Ebs.[SnapshotId]" \
    --output text`

    echo "deregister image $ami_id"
    aws ec2 deregister-image --image-id=$ami_id
    for snapshot_id in $snapshot_ids;do
        echo "delete snapshot $snapshot_id"
        aws ec2 delete-snapshot --snapshot-id=$snapshot_id
    done
  done
}
lsami() {
  local  key='*'
  if [ "$1" != "" ]; then
    key=$1
  fi
  aws ec2 describe-images --owner self \
  --filter "Name=name,Values=$key" \
  --query "sort_by(Images[].{name:Name,image:ImageId,date:CreationDate,state:State},&name)" \
  --output table
}

# network
lseni()
{
    aws ec2 describe-network-interfaces --query 'NetworkInterfaces[].[PrivateIpAddress,Association.PublicIp]' --output text
}

lsvpc() {
  aws ec2 describe-vpcs \
  --output text \
  --query 'Vpcs[].[CidrBlock,VpcId]'
}

lsvpc-sub() {
  aws ec2 describe-subnets \
  --output text \
  --query 'Subnets[].[AvailabilityZone,CidrBlock,SubnetId,VpcId,Tags[?Key==`Name`].Value|[0]]'
}

lsvpc-pl() {
  aws ec2 describe-managed-prefix-lists \
  --output text \
  --query 'PrefixLists[].[PrefixListId,PrefixListName]'
}



CloudWatchLogs関連


lslog(){
  local cond=""
  if [ "$1" != "" ]; then
    cond=$(printf '?contains(logGroupName,`%s`)' $1)
  fi
  aws logs describe-log-groups --query "sort_by(logGroups[$cond].{name:logGroupName,bytes:storedBytes},&name)" --output table
}
rmlog(){
  if [ $# -eq 0 ]; then
    echo "usage: rmlog <log group name>"
    return
  fi
  aws logs delete-log-group --log-group-name $1
}
taillog(){
  if [ $# -eq 0 ]; then
    echo "usage: taillog <log group name>"
    return
  fi
  aws logs tail $1 --follow --since 1h
}

CloudFormation


lsstack() {
  aws cloudformation describe-stacks \
  --query "Stacks[?contains(StackName,\`$1\`)].{StackName:StackName,StackStatus:StackStatus,Desc:Description}" \
  --output table
}
rmstack() {
  rain rm $1
}


ECS/EKS/ECR


# ecr
lsecr-repo() {
  aws ecr describe-repositories --query 'repositories[].repositoryName' --output text | tr "\t" "\n"
}

lsecr-img() {
  if [ $# -eq 0 ]; then
    echo "usage: lsecr-img <repository name>"
    return
  fi
  aws ecr list-images --repository-name $1 --query 'imageIds[].imageTag' --output text
}

rmecr-img() {
  if [ $# -eq 0 ]; then
    echo "usage: rmecr-img <repository name> <tag>"
    return
  fi
  aws ecr batch-delete-image --repository-name $1 --image-ids imageTag=$2
}

# ecs
lsecs() {
  local keyword=.
  if [ $# -ne 0 ]; then
    keyword=$1
  fi
  aws ecs list-clusters | jq -r '.clusterArns[]' | cut -d/ -f2 | grep -i $keyword | sort
}
lsecs-task() {
  if [ $# -eq 0 ]; then
    echo "usage: lsecs-task <cluster name>"
    return
  fi
  local cluster=$1
  local tasks=$(aws ecs list-tasks --cluster $cluster --query 'taskArns[]' --output text | tr "\t" " ")
  aws ecs describe-tasks --tasks $tasks --output table \
    --cluster $cluster \
    --query 'tasks[].[group,taskArn, attachments[0].details[?name==`privateIPv4Address`]|[0].value, capacityProviderName, lastStatus]'
}

# eks
lseks() {
  local keyword=.
  if [ $# -ne 0 ]; then
    keyword=$1
  fi
  aws eks list-clusters | jq -r '.clusters[]'| grep -i $keyword | sort
}


SSM


 alias lsssm='aws ssm describe-parameters --query 'Parameters[].[Name]' --output text | sort'


おまけ


上記コマンドを使用して作業している様子です。(動画)

terraformでAWS環境を構築しながら上記コマンドで構築結果を確認しています。


 

2023年2月5日日曜日

EKS(fargate)でargocdを試す環境をterraformで作ってみた

 

やりたかったこと

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


私の環境

  • SparkyLinux6.5(Debian系)
    • ssh秘密鍵(レポジトリアクセス用)
  • k8s
    • kubectl1.25.4
    • helm3.10.2
  • aws
    • aws-cli2.9.4
    • ssh秘密鍵(EC2用キーペア)
  • terraform
    • tfenv3.0.0
    • tflint0.43.0
    • terraform1.3.7


主に、下記のサイトを参考にしました。


サンプルコード


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


構成


.
├── Makefile
├── README.md
├── app/
│   ├── nginx/
│   │   ├── README.md
│   │   ├── deployment.yml
│   │   ├── hpa.yaml
│   │   └── service.yml
│   └── php/
│       ├── README.md
│       ├── deployment.yml
│       ├── hpa.yaml
│       └── service.yml
├── demo_todo_k8s.org
├── global/
│   ├── backend.tf
│   ├── ip.sh
│   ├── ip_pub.sh
│   ├── locals.tf
│   ├── providers_aws.tf
│   ├── providers_localstack.tf
│   └── versions.tf
├── modules/
│   └── ec2-spot/
│       ├── main.tf
│       ├── outputs.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_eks/
│   ├── 00_check/
│   │   ├── Makefile
│   │   └── outputs.tf
│   ├── 01_vpc/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   └── main.tf
│   ├── 02_ssm/
│   │   ├── Makefile
│   │   └── main.tf
│   ├── 10_eks_cluster/
│   │   ├── Makefile
│   │   ├── aws_fargate_profile_app.tf
│   │   ├── aws_fargate_profile_kube_system.tf
│   │   ├── aws_iam_oidc.tf
│   │   ├── datasources.tf
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 20_k8s_alb_controller/
│   │   ├── AWSLoadBalancerController.json
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── iam.tf
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 20_k8s_eso/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── external_secrets_policy.json
│   │   ├── iam.tf
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 20_k8s_metrics_server/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 21_k8s_argocd/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── ingress.tf
│   │   ├── k8s_external_secret.yaml
│   │   ├── k8s_repo.yaml
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   ├── repo.tf
│   │   └── versions.tf
│   ├── 21_k8s_dashboard/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── ingress.tf
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── 40_app_argocd/
│   │   ├── Makefile
│   │   ├── datasources.tf
│   │   ├── ingress.tf
│   │   ├── k8s_argo_app.yaml
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   └── versions.tf
│   ├── Makefile
│   ├── README.md
│   ├── locals_all.tf
│   └── locals_prd.tf
└── stacks_template/
    ├── 00_check/
    │   ├── Makefile
    │   └── outputs.tf
    ├── Makefile
    ├── locals_all.tf
    ├── locals_dev.tf
    ├── locals_prd.tf
    └── locals_stg.tf

こんなイメージ


この構成の説明と基本操作方法は、下記の別記事を参照。
EKS環境は、前述の別記事(DockerDesktop版)と比較して、下記を変えてます。
  • app/には、deploymentとhpa,searviceのmanifestをおいてます。移動した理由は、argocdでの見え方の違いを試したかったから。
    ちなみに、ingressをapp/に移動しなかったのは、ALBを削除しないと、EKSを破棄できないから。(make destroy で一括破棄ができなくなる)
  • app/には、nginx, phpの2種類をおいてます。phpはhpaのスケールアウト確認用です。
  • ingress nginxのかわりにAWS Load Balancer Controllerを使ってます。
  • ALBは、自分のpublic ipのみ許可するようにSecurityGroupを設定しています。
    (public ipの取得は、global/ip_pub.sh で実施)


構築


準備


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

awscli 
AWS用のprofile名は "sandbox" を使用します。

ec2キーペア
NATインスタンスで使用するキーペアです。"sandbox"を使用します。
節約のためにNATゲートウェイでなくNATインスタンスを使ってます。

Terraform実行


下記コマンドを実行すると、terraform applyが実行されます。
これで、AWSのEKS環境にリソース一式(vpc, eks, ssm, argocd, dashbord, etc)が構築されます。
$ make opply ENV=prd OPT="-auto-approve" -C stacks_base
$ make apply ENV=prd OPT="-auto-approve" -C stacks_eks


確認


EKSへのkubectl接続

下記コマンドで config を更新

aws eks update-kubeconfig --name eks-main --alias eks-main

EKS作成者だけアクセスできます。

EKSへのアクアセス権限設定については下記URL参照


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

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

app(nginx/php)のページ
http://<ALBのDNS>
nginx(welcome ページ), php(OK)が表示されます。


破棄


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


おまけ


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


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