kubectl port-forwardでクラスタ外からPodにアクセスする
Cluster内にIngressを立てたがうまく動作しないことがあり、デバッグのためPod内のアプリケーションにアクセスしたいと思った。今までは、テスト用のPodを立ててその中からcurl等でリクエストを送っていた。
kubectl run test-pod --image nginx -- /bin/sh -c 'curl <target_pod's_ip_address>'
しかし、 kubectl port-forward
コマンドを使うことで、テスト用Podなしでデバッグができることを教えてもらった。
kubectl port-forward <target_pod's_name> 8080:80
このようにすることで、ホストの8080番ポートがPodの80番ポートにPort-forwardingされるため、 localhost:8080
でアクセスが可能になる。ブラウザで見られるのがありがたい。
kubectl port-forward
のオプションにはServiceも指定できるが、内部的にはPodを指定するのと同じであり、ClusterIPを通さず直接Podにアクセスしていることに注意したい。ClusterIPにアクセスしたい場合は以下の記事が参考になる。
sh -cでコマンドを渡すときはシングルクォートを使う
KubernetesのPod内の環境変数が正しく設定されているかを確認しようとして、以下のようにしたところ、何も出力されなかった。
$ kubectl exec -it pod_name -- /bin/sh -c "echo $VAR_NAME"
Podの中に入って確認すると正しく出る。
$ kubectl exec -it pod_name -- /bin/sh # echo $VAR_NAME test
これは、 /bin/sh -c
に渡したコマンドがダブルクォートだったことが原因。 sh -c
を使うと、 -c
以下で渡したコマンドを sh
で実行させることができるが、ダブルクォートにしてしまうと kubectl
を実行しているシェルで変数が解釈されてしまう。 $VAR_NAME
という環境変数はPodの中にはあるがhostでは設定されていないので、単なる echo
を渡していることと同じになり、何も出力されずに終わる。
正しく確認するには、シングルクォートで渡せば良い。シングルクォートで囲われた内容は展開されないため、 $VAR_NAME
がPodに渡る。
$ kubectl exec -it pod_name -- /bin/sh -c 'echo $VAR_NAME' test
netcatのzero I/Oモードで疎通確認する
疎通確認をする際はcurlかwgetを使うことが多かったが、CKADの講座で講師がnetcatを使っているのを見て調べてみた。
netcatはサービスとの通信を確認できるコマンドであり、たいていのLinuxディストリビューションに同梱されている。KubernetesのPodに入ってコマンドを打つ場合、imageにcurlが入っていないというようなことも多いので、使えるようにしておくと便利かもしれない。
netcatでの通信は、基本的に相手のホスト名とポートを指定すればよい。
nc google.com 80
これに加え、netcatではzero I/Oモードを使ったポートスキャンを行うことができる。これはパケットを飛ばさず、相手のポートに接続できるかのみを確認するモードで、接続に成功すればすぐに接続が閉じられる。実際にデータのリクエスト・レスポンスをすることがないので、疎通確認に適している。
CKAD講座では、Podの中からService名を指定して疎通できるか確認していた。
nc -z -v -w 1 service-name 80
-z
でzero I/Oモードを使える。 -v
は詳細な出力をするオプション。 -w
はタイムアウト判定までの秒数を指定するもので、これを指定しないと接続に失敗した場合コマンドが終了しない。
【GitHub Actions】AWS Lambdaの環境変数を自動で更新する
最近システムのリリースフローの自動化を進めることが多い。先日はLambda関数の更新の自動化を行った。この関数は環境変数を持っており、これを頻繁に更新する必要があった。
新しい環境変数をどのように渡すかが最も難しいポイントだったが、この環境変数はAWS CLIコマンドにおいてJSONファイル形式で渡すことができる。
aws lambda update-function-configuration --function-name "${function_name}" --environment fileb://env.json
--environment
オプションの後にファイルパスを指定する。 AWS CLIでは fileb://
とつけることで、ファイルの中身をバイナリコンテンツとして渡すことができる。面倒なファイル読み込みの処理を書かずに済むため、この記法はとても気に入っている。また、このJSONファイルをGitHub上に置けるため、環境変数のバージョン管理がしやすくなるという利点もある。
JSONファイルのフォーマットは以下の通り。 SECRET_ENV
は機密性の高い環境変数であり、値はGitHub ActionsのSecretsに登録してある。JSONファイル上では値を適当なものにしておく。
# env.json { "Variables": { "NORMAL_ENV": "example", "SECRET_ENV": "to_be_converted" } }
workflowファイルには以下のように記載する。 jq
コマンドでJSONファイルの SECRET_ENV
の値を置換しているのがポイント。 --arg
オプションとして secret_env
として ${{ secrets.SECRET_ENV }}
の値を渡し、その値をJSONファイル内の to_be_converted
と入れ替えている。
- name: Update lambda envvar env: LAMBDA_FUNCTION_NAME: dev_function ENV_JSON_FILE: env.json SECRET_ENV: ${{ secrets.SECRET_ENV }} run: | jq --arg secret_env "${SECRET_ENV}" '.Variables.SECRET_ENV = $secret_env' "${ENV_JSON_FILE}" > env_converted.json aws lambda update-function-configuration --function-name "${LAMBDA_FUNCTION_NAME}" --environment fileb://env_converted.json
【Kubernetes】--dry-runでmanifestファイルの雛形を手に入れる
CKAD対策で学んだtips。
Kubernetes上のリソースを作る際、複雑な設定の場合はmanifestファイルを書かなければいけない。しかしYAML形式で記述を行うのはとても時間がかかるうえ、それぞれのリソース種別ごとの記法を全部は覚えられない。公式ドキュメントからコピペしてくることもできるが、それも探すのが面倒なうえタイムロスになる。
そこで、manifestファイルの雛形を手に入れたいときは --dry-run
が役立つ。
--dry-run
はkubectlコマンドのオプションで、 apply
や create
を実行せず、クライアントサイドでできるバリデーションを行ってくれる。この出力をYAML形式でファイルに書き出せば、それがmanifestファイルの雛形になる。
$ kubectl run nginx --image=nginx --dry-run=client -o yaml > nginx.yaml $ cat nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: run: nginx name: nginx spec: replicas: 1 selector: matchLabels: run: nginx strategy: {} template: metadata: creationTimestamp: null labels: run: nginx spec: containers: - image: nginx name: nginx resources: {} status: {}
これをもとに各項目の値を変えることができる。ゼロからmanifestファイルを作るよりはるかに楽。
なお、設定すべき項目のうちコマンド上で設定できるオプションをあらかじめ設定してファイルに出力すると、作業がより効率的になる。
【GitHub Actions】ファイルパスのワイルドカード指定には「*」では不十分
先日いつものようにプルリクエストを作ったら、GitHub Actionsのworkflowが全く動いてくれなかった。GitHub ActionsのSpending limitやGitHub自体の障害も疑ったが、原因はもっと単純なものだった。
yamlファイルでは、 on
節を以下のように記述していた。
on: pull_request: branches: - master paths: - '*' - '!README.md' - '!.gitignore' - '!.github/workflows/dev-workflow.yaml' - '!.github/workflows/release-workflow.yaml' ...
これでコードのファイルは全て検知すると思っていたが、 *
を指定していたのが問題だった。GitHub Actionsでは、 *
ではスラッシュにマッチしないため、これではトップディレクトリにあるファイルしか検知してくれない。
workflowが動かなかったプルリクエストでは、 src/main.py
のみに差分があったため、上記の条件では検知されなかった。それ以前のプルリクエストでは、READMEやworkflowファイルを合わせて更新していたので、たまたま問題なかっただけだった。
サブディレクトリ以下にあるファイルにもマッチさせたい場合、 **
と指定すればよい。
on: pull_request: branches: - master paths: - '**' - '!README.md' - '!.gitignore' - '!.github/workflows/dev-workflow.yaml' - '!.github/workflows/release-workflow.yaml' ...
ただ、このように「少数のファイル以外全てにマッチさせたい」という場合、 paths-ignore
を使う方がより単純に書ける。
on: pull_request: branches: - master paths-ignore: - 'README.md' - '.gitignore' - '.github/workflows/dev-workflow.yaml' - '.github/workflows/release-workflow.yaml' ...
【GitHub Actions】docker-build-pushでECRにimageをpushする
GitHub Actionsでworkflowを書くとき、imageをビルドしてECRにpushする処理を書く機会が多い。今までは以下の様に書いていた。
jobs: build: name: Build and push Docker image runs-on: ubuntu-latest env: IMAGE_NAME: ${{ secrets.CONTAINER_REGISTRY_PATH }}/path/to/ecr/repo IMAGE_TAG: ${GITHUB_SHA} steps: - uses: actions/checkout@master - name: Login to ECR env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: $(aws ecr get-login --no-include-email) - name: Build image run: docker build -t ${IMAGE_NAME}:${IMAGE_TAG} . - name: Push image run: docker push ${IMAGE_NAME}:${IMAGE_TAG}
しかし先日、良さそうなライブラリを教えてもらった。
Docker Imageのビルドからレポジトリへのログイン・pushまでを行ってくれるライブラリで、push先もDockerHub, GCR, ECR, GitHub Docker Registryに対応している。
ECRにpushする場合は以下のように書ける。
jobs: build: name: Build and push Docker image runs-on: ubuntu-latest steps: - uses: actions/checkout@master - uses: mr-smithers-excellent/docker-build-push@v4 name: Build & push Docker image with: image: path/to/ecr/repo tag: ${GITHUB_SHA} registry: ${{ secrets.CONTAINER_REGISTRY_PATH }} env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
docker image関連のステップ数を大幅に減らすことができ、workflowが見やすくなる。
念のためコードも確認してみる。
docker-build-push/docker.js at master · mr-smithers-excellent/docker-build-push · GitHub
docker関連の処理はdocker.js
に記述されている。ECRの場合 aws ecr get-login
でログインを行い、その後 docker build
, docker push
を行うというよくある処理になっている。