Node.jsでsleep相当のことをする
非同期処理が意図通り動いているのか確認するときに便利です。 resolveAfter2Secondsという関数を定義し、完了を待ちます。
async function slowSomething(){ await resolveAfter2Seconds() } function resolveAfter2Seconds() { console.log('starting slow promise') return new Promise(resolve => { setTimeout(function() { resolve('slow') console.log('starting slow promise') }, 2000) }) }
セキュアなパスワードを生成するワンライナー
いつも忘れて検索してるのでここに残しておく
ruby -r securerandom -e "puts SecureRandom.urlsafe_base64"
GKEでスティッキーセッション(Session Affinity)を利用する
GKE環境でスティッキーセッションを利用するときの方法です。WebSocketなど利用していて、ブラウザからPodと接続を確立したあとはそのPodと通信し続けたい場合に必要になると思います。
k8s環境でスティッキーセッションってそもそもできるのか?と最初不安だったのですが、思ったより簡単にできました。 GCPやそのほかのドキュメントではSessionAffinityと呼ばれていたので以降SessionAffinityにします。
解決策
GKEデフォルトのIngress Controllerには、SessionAffinityの機能があり、この機能を有効にすることで実現することができます。接続元の判断は、クライアントIP、Cookieのどちらかの方法を選ぶことができます。
Configuring a backend service through Ingress | Kubernetes Engine Documentation | Google Cloud
ドキュメントに書いてある通りなのですが、まずbackend configを作成し
apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: my-bsc-backendconfig spec: timeoutSec: 40 connectionDraining: drainingTimeoutSec: 60 sessionAffinity: affinityType: "CLIENT_IP"
サービス側でそのbackend configを利用することで実現できます。
ind: Service metadata: name: my-bsc-service labels: purpose: bsc-config-demo annotations: cloud.google.com/neg: '{"ingress": true}' beta.cloud.google.com/backend-config: '{"ports": {"80":"my-bsc-backendconfig"}}' ...
サービス側で指定するNEGは必須です。 また、ServiceがNEGを利用していなかった場合、NEGに切り替わるまでの間通信断が発生するので本番環境に反映する場合は注意が必要です。
仕組み
GCPのLoadBalncerにSession Affinity ( https://cloud.google.com/load-balancing/docs/backend-service#generated_cookie_affinity )という仕組みがあり、これをそのままGKEでも利用する形です。
通常のk8s環境の場合、Ingressとして作成されたLBのバックエンドはGCEインスタンスであり、GCEインスタンスに来たリクエストをk8sがPodに転送するので一見SessionAffinityの実現は困難なように思えます。そこで、必要になるのがNEG( https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing )です。
NEGを利用すると、LBのバックエンドをGCEインスタンスではなく、Podにすることが可能になります。こうすることで、LoadBalancerのSession Affinityの機能をk8s環境でもそのまま利用することができます。
NEGはGKE独自の機能なので、GKE以外の環境では、Nginx Ingress Controllerを利用する必要がありそうでした
Telepresenceを使ってk8s環境の開発をより快適にする
Telepresence(https://www.telepresence.io/)をちょっと試してみたのでそのメモ
Telepresence?
ローカルPCとリモートのk8sクラスタを接続し、マイクロサービス 環境での開発を支援してくれるツールです。 出来ることは大きく2つで、
どちらも双方向のプロキシがk8sクラスタにPodとしてデプロイされ、k8sクラスタとローカルPCを接続してくれます。
Install
Macであれば
brew cask install osxfuse brew install datawire/blackbird/telepresence
だけでインストールできます。
WindowsはWSL上で動作させる形になっています。(これをWindows Supportというのかどうかは微妙なところ)
詳しくはこちら
Deploymentの差し替え
おそらくこれがメインの用途です。 k8sクラスタ上のアプリケーションでデバッグ情報を取得する場合、これまではデバッグ用の設定を追加したコンテナを作成しそれをデプロイする必要がありましたが、その必要がなくなります。
たとえば、service_aというdeploymentのapp というcontainerをローカルに存在するapp:debug というコンテナに差し替える場合
telepresence --swap-deployment service_a:app --docker-run --rm -it app:debug
というコマンドで差し替えることができます。Containerの指定は、Pod内のContainerが1つしかないなら不要です。SidecarなどでPod内に複数のContainerが存在しているケースが多いと思うので、Containerは必ず指定しておいた方が良いと思います。
注意点としては、このDeploymentの差し替えはTelepresence利用者だけに影響があるものではありません。k8sクラスタのDeploymentのそのものに影響を与えています。複数の開発者でクラスタを共有している場合は注意が必要です。
クラスタが外部からアクセス可能な場合、外部からローカルPC上のコンテナにアクセスできてしまいます。デバッグ用のコンテナとはいえ、不用意にファイルを配置しないように気をつけましょう。特にボリュームマウントする場合は注意が必要です。
ある程度の規模のクラスタになると、CI/CDの観点から各自が自由にkubectl applyはできなくなり、CIツールのチェックが通ったものが反映されるようなフローになることが多くなってくると思います。それはそれで正しいのですが、ちょっとした検証のためにそのフローを通さないといけないのは非効率です。このdeploymentの差し替えを有効に利用すれば、別のサービスとの連携の検証などが素早く行えそうです。
k8sクラスタへの接続
引数なしでtelepresenceコマンドを実行すると、ローカルPCとk8sクラスタを接続することができます。
telepresence
デフォルトではkubectlのcurrent contextが利用されます。context パラメタとnamespaceパラメタをそれぞれ指定することができます。
telepresenceによる接続が有効な間は、ローカルPCがk8sクラスタ内に存在しているようなイメージになります。サービスの名前解決を行うことができ、port-forwardで直接Podに接続するよりもより実際の動作に近い挙動を確認できます。また、ローカルPCにインストールされている様々なツールがそのまま利用できます。
まとめ
これまでのk8sクラスタの開発ではリモートのk8sクラスタをデバッグする場合、kubectl port-forward で特定のPodで接続したり、デバッグ用のPodを準備しておいてそれをデプロイしそのPodのターミナルからデバッグを行うというプラクティスが紹介されることが多かったですが、telepresenceも選択肢の1つとして用意しておくとより快適な開発を行えそうです。
GKEでノードをダウンタイムなしで更新する場合
GKEを利用していて、ノードをダウンタイムなしで更新したい場合、ノードプールを新規作成し、既存のノードプールからワークロードを移行することで実現することができます。
ノードのスペックやサービスアカウント の情報は作成後変更はできないため、本番環境で運用を始めると必要になるケースが多そうです。
ワークロードの移行は、既存のNode全てにcordonを実行しUnscheduleにしてから、既存のNode全てをdrainすることでワークロードを新しいノードプールに移行できます。 このオペーレションをダウンタイムなしで実現するには、PodDisruptionBudgetが適切に設定されている必要があるので注意が必要です。
詳しくは↓に全て書いてあります。 cloud.google.com
gitで、ある2つのブランチ間の特定のディレクトリ配下のdiffを取る
やりたいことはタイトルの通り。
特定のディレクトリ配下に変更があったかどうかを知りたい場合の方法です。調べて見たら出来ました。
git diff branchA branchB --relative=dir_name
で出来ます。
ファイル名のみで良い場合は、
git diff branchA branchB --relative=dir_name --name-only
readnessProve, livenessProveを設定していない場合の挙動
readnessProve, livenessProveを設定していない場合、両者ともstateのデフォルト値がSuccessになる。つまりチェックされない。
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
livenessProbe: Indicates whether the Container is running. If the liveness probe fails, the kubelet kills the Container, and the Container is subjected to its restart policy. If a Container does not provide a liveness probe, the default state is Success.
readinessProbe: Indicates whether the Container is ready to service requests. If the readiness probe fails, the endpoints controller removes the Pod’s IP address from the endpoints of all Services that match the Pod. The default state of readiness before the initial delay is Failure. If a Container does not provide a readiness probe, the default state is Success.
という記述があった。 何らかデフォルトのヘルスチェックが入っているのかと思ったがそうではなかったのでメモしとく