「おじいちゃん kubernetesってなに?」「...それはコスモスじゃよ」(3) -運用編-


おはこんばんにちは
zerobillbank株式会社のインフラエンジニアtomatoことtomatoです。

今回はkubernetesシリーズの最終回ということで、
構築時のトラブルシューティングから運用・監視についてお話していきたいと思いまうす

ちなみに前回の記事はこちらです
「おじいちゃん kubernetesってなに?」「...それはコスモスじゃよ」(1) -概要編-
「おじいちゃん kubernetesってなに?」「...それはコスモスじゃよ」(2) -構築編-

構築のトラブルシューティング

構築時のエラーに対応として、まずPodで起こっているエラーか、
それ以外で起こっているエラーかを分類するといいと思います。

Podのエラー

Podでエラーが起こっているかを確認するのは簡単です。
kubectl get poPodを確認した時に、正常時の場合はSTATUSRunnningSTATUS1/1のように分母と分子が等しくなっているはずです。

$ kubectl get po
NAME                          READY   STATUS               RESTARTS   AGE
sample-775487cf8-d5czn        0/1     ImagePullBackOff     2          15m

それ以外の場合はエラーが出ていますので、
describeコマンドを使ってエラーの原因を確認します。

$ kubectl describe po sample-775487cf8-d5czn

---省略
Events:
  Type     Reason     Age               From                      Message
  ----     ------     ----              ----                      -------
  Normal   BackOff    28s (x4 over 1m)  kubelet, ip-xxx.internal  Back-off pulling image "nginx:1.123"
  Warning  Failed     28s (x4 over 1m)  kubelet, ip-xxx.internal  Error: ImagePullBackOff

describeコマンドで対象のPodを調べると、Eventsの欄にエラーイベントが出力されます。
上記の例では存在しないnginxのバージョンを指定したため、イメージがpullできないエラーが出ていました。

調査系コマンド

上記のdescribeコマンドでも調査は可能ですが、
多くのケースでは下記の2つのコマンドのどちらかを打てば
エラー原因を見つけることができます。

logsコマンド

kubectl logs [deployment名]

get events

kubetctl get events | grep [deployment名]

アクセスできないエラー

上記以外でPodは正常に稼働しているにも関わらず
Webページなどが上手くアクセスできない場合についての対処方法についてです。

この場合、どこでアクセスが途切れているかを下記のステップで特定します。

  1. Podでのアクセス確認
  2. Service経由でのアクセス確認
  3. Ingress経由でのアクセス確認

Podでのアクセス確認

$ kubectl exec -it [Pod名] -- /bin/sh

alpineなどは操作系のツールが入っていないことが多いため、
その場合は下記のコマンドでインストールします。

# update
apt update
# curlのインストール
apt install -y curl
# netstatのインストール
apt install -y net-tools

# aptがない場合
apk -U add curl
apk add net-tools

動いているプロセスの確認

$ netstat -pant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:3000              0.0.0.0:*               LISTEN      1/nginx: master pro

上記コマンドで、対象のアプリケーションが動作している事と
動いているPort番号を確認します。

$ curl http://localhost:3000
welcome nginx!!

これで表示されれば 1. Podでのアクセス確認 は問題なしです。

Service経由でのアクセス確認

$ curl http://nginx:3000
welcome nginx!!

これで表示されれば 2. Service経由でのアクセス確認 は問題なしです。

よくあるミスとしては、service.yamlの中のportsの項目の
porttargetPortの記載ミスです。

nginx/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: sample
  labels:
    app: nginx
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 80 # Default port for image
      targetPort: 80

port... image内でのPort番号。上記のPod内でnetstatした場合のPort番号になる。
targetPort... kubernetes上のPort番号。Serviceに紐付く。

この場合、image内でのPort番号は3000なので、port80ではなく3000と記載します。

またdeployment.yaml内にもcontainerPortという項目があり
こちらはservice.yamltargetPortと合わせる必要があります。

Ingress経由でのアクセス確認

上記までで問題がなくてアクセスできない場合は、ドメイン周りの問題が考えられます。
実際にページにアクセスした際のエラーメッセージを基に
ドメインやSSL証明書周りを確認してみてください。

運用

kubernetesではyamlで管理することで冪等性を担保していますが
運用に置いてyamlの取り扱いで気をつけたほうがいいなーと思う点をあげてみます。

applyの前にはdiffを取る

applyコマンドで適用をする前に、必ずdiffコマンドで差分確認をしましょう。
想定外のyamlを当ててしまう事故を防げます。

# 想定の差分が出ることを確認
$ kubectl diff -f nginx/deployment.yaml
# 適用
$ kubectl apply -f nginx/deployment.yaml
# 差分が出ないことを確認
$ kubectl diff -f nginx/deployment.yaml

更新の際にはrolloutコマンドを用いる

Podの更新の際はdeleteコマンドではなく、rollout restartコマンドを使用します。
deleteコマンドでPodを削除しても、deploymentが存在していればPodは再起動されますが
削除してから再起動する間にサービスダウンが発生します。
rollout restartコマンドであれば、古いPodを残しつつ、新しいPodに順次移行してくれるため、サービスダウンなく再起動をすることができます。

configsecretなどのリソースのみを更新する場合、Podが再起動されないと
新しい定義が読み込まれませんので、その際もrollout restartコマンドを忘れずに実行しましょう。

$ kubectl rollout restart deploy/nginx
deployment.apps/nginx restarted

おまけ

kubectl api-resourcesと打つと、利用できるリソースの一覧を表示できます。
さらにリソースごとのショートカットの名前と、yamlに記載するapiVersionも確認できるので
何かあった時に覚えておくと便利なコマンドです。

$ kubectl api-resources

NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND
bindings                                                                      true         Binding
componentstatuses                 cs                                          false        ComponentStatus
configmaps                        cm                                          true         ConfigMap
endpoints                         ep                                          true         Endpoints
events                            ev                                          true         Event
limitranges                       limits                                      true         LimitRange
namespaces                        ns                                          false        Namespace
nodes                             no                                          false        Node
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
pods                              po                                          true         Pod
...

監視

監視については色々なツールがあると思いますが、
まず手軽にやるのなら下記のツールと相性が良いと思います。
無料でUIによるログ表示から、アラート発報まで一通り必要なことができちゃいます

またhelm(パッケージ管理ツール)が3系になり、とても導入が楽になりました。
ただし、デフォルト設定のまま適用すると、どんな値なのかの認識や管理ができないため
一旦ローカルにfetchしてからinstallするのが良いのではと思います。

各設定値についてはvalues.yamlに記載されてますので
変更したい項目を見つけて値をいじるとinstallもしくはupgradeの際に適用されます。

インストール

helmのインストールについては下記を参照してください。
https://helm.sh/ja/docs/intro/install/

fetchする

$ helm repo update

$ helm fetch stable/filebeat
$ helm fetch stable/logstash
$ helm fetch stable/elasticsearch
$ helm fetch stable/kibana
$ helm fetch grafana/grafana

$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
$ helm repo update
$ helm fetch prometheus-community/kube-prometheus-stack

installする

$ helm install -name filebeat -n monitoring -f filebeat/values.yaml stable/filebeat
$ helm install -name logstash -n monitoring -f logstash/values.yaml stable/logstash
$ helm install -name elasticsearch -n monitoring -f elasticsearch/values.yaml stable/elasticsearch
$ helm install -name kibana -n monitoring -f kibana/values.yaml stable/kibana
$ helm install -name grafana -n monitoring -f grafana/values.yaml grafana/grafana
$ helm install -name prometheus -n monitoring -f kube-prometheus-stack/values.yaml prometheus-community/kube-prometheus-stack

インストールはこれだけですのでとても簡単!
ちなみに更新したいときはinstallの部分をupgradeに変えるだけです。

Grafanaは設定周りがちょっとややこしいので、以前に書いた下記の記事を参考にしていただければと。
helm3を使用して超簡単にkubernetesにGrafanaをデプロイする方法がまるでtomato

おわり

というわけで全3回に渡ってkubernetesについて解説していきました。
気づいた点があれば随時加筆していきたいと思います。
一人でも多くkubernetes沼にハマってくれるエンジニアが増えてくれればいいなと思っております。
みなさま良いkubernetesライフを!!

ではまた🙋‍♂️

さいごに

ZEROBILLBANKでは一緒に働く仲間を募集中です。
なんとかjsとか、ブロックチェーンとか、kubernetesとかでいろんなAPIを作るお仕事。
今のところエンジニアは5人くらい。スタートアップだけど、結構ホワイトで働きやすいです。

ZEROBILLBANK JAPAN Inc.