サイドカーコンテナの追加

KubernetesBeginner
オンラインで実践に進む

はじめに

サイドカーコンテナは、アプリケーションコンテナと同じ Pod 内で動作し、アプリケーションの実行をサポートするコンテナです。これは、アプリ起動前に完了しなければならないイニシャルコンテナ(init container)とは異なります。サイドカーは一般的に、ログの転送、プロキシ、同期、あるいは Pod のライフサイクルを共有すべきその他の補助的な機能のために使用されます。

この実験では、共有の emptyDir ボリュームにログを書き込むアプリコンテナと、そのファイルを追跡(フォロー)するサイドカーコンテナを持つマルチコンテナ Pod を作成します。両方のコンテナを調査し、サイドカーのログを読み取った後、同じサイドカーパターンを Deployment テンプレートに適用します。

サイドカー用名前空間の準備

このステップでは、サイドカーの練習用にクリーンな名前空間を準備します。

/home/labex/project から開始します。このディレクトリ内に Pod マニフェストと Deployment マニフェストを作成します。

mkdir -p /home/labex/project
cd /home/labex/project

Kubernetes API サーバーに到達可能か確認します。VM が起動した直後でノードの準備ができていない場合は、数秒待ってから再度コマンドを実行してください。

kubectl get nodes --request-timeout=5s

期待される出力例:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

ワークロードを作成する前に、クラスターのネットワーク Pod が Ready 状態になるまで待ちます。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

期待される出力:

pod/calico-node-... condition met

ckad-prep-sidecar という名前の名前空間を作成します。

kubectl create namespace ckad-prep-sidecar

この名前空間を現在のコンテキストの名前空間として設定します。

kubectl config set-context --current --namespace=ckad-prep-sidecar

現在の名前空間を確認します。

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

期待される出力:

ckad-prep-sidecar

マルチコンテナ Pod の作成

このステップでは、アプリケーションコンテナとサイドカーコンテナを持つ Pod を作成します。

両方のコンテナは、同じ emptyDir ボリュームを /var/log/shared にマウントします。アプリコンテナは /var/log/shared/app.log にログ行を書き込みます。サイドカーコンテナは同時に実行され、tail -f を使用してそのファイルをストリーミングします。touch コマンドは tail -f が開始される前にファイルを作成するため、アプリがまだ最初の行を書き込んでいない場合でも、サイドカーは安全に待機できます。

sidecar-pod.yaml を作成します。

cat > sidecar-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: sidecar-demo
  labels:
    app: sidecar-demo
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: shared-logs
    emptyDir: {}
  containers:
  - name: app
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'i=1; while true; do echo "app-line-${i}" >> /var/log/shared/app.log; i=$((i+1)); sleep 2; done'
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/shared
  - name: log-sidecar
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'touch /var/log/shared/app.log; tail -n +1 -f /var/log/shared/app.log'
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/shared
EOF

マニフェストを適用します。

kubectl apply -f sidecar-pod.yaml

期待される出力:

pod/sidecar-demo created

Pod が Ready になるまで待ちます。マルチコンテナ Pod は、すべての通常のコンテナが準備完了になったときにのみ Ready とみなされます。

kubectl wait --for=condition=Ready pod/sidecar-demo --timeout=120s

期待される出力:

pod/sidecar-demo condition met

Pod 内のコンテナ名を表示します。

kubectl get pod sidecar-demo -o 'jsonpath={.spec.containers[*].name}{"\n"}'

期待される出力:

app log-sidecar

サイドカーの連携を確認する

このステップでは、両方のコンテナが実行されており、サイドカーがアプリのログファイルをストリーミングしていることを確認します。

まず、コンテナの準備状況を確認します。出力には各コンテナ名と準備完了状態が表示されます。

kubectl get pod sidecar-demo -o 'jsonpath={range .status.containerStatuses[*]}{.name}{" "}{.ready}{"\n"}{end}'

期待される出力例:

app true
log-sidecar true

アプリコンテナのログを読み取ります。アプリはシェルコマンドが開始されたときにのみ標準出力に書き込みを行い、繰り返される行は共有ファイルに書き込まれます。

kubectl logs sidecar-demo -c app --tail=5

アプリコンテナは標準出力に繰り返し行を出力しない場合があります。重要な証拠は共有ファイルとサイドカーのログにあります。

アプリコンテナ経由で共有ファイルを読み取ります。

kubectl exec sidecar-demo -c app -- sh -c 'tail -n 3 /var/log/shared/app.log'

期待される出力にはアプリのログ行が含まれます。

app-line-...
app-line-...
app-line-...

次に、サイドカーのログを読み取ります。サイドカーは同じファイルを追跡しているため、そのログには同様の行が含まれているはずです。

kubectl logs sidecar-demo -c log-sidecar --tail=3

期待される出力:

app-line-...
app-line-...
app-line-...

Deployment へのサイドカーパターンの追加

このステップでは、サイドカーパターンを Deployment テンプレートに組み込みます。

単独の Pod は学習には役立ちますが、アプリケーションは通常コントローラーを通じて実行されます。Deployment は代替 Pod を作成でき、各代替 Pod にはテンプレートからアプリコンテナとサイドカーコンテナの両方が含まれます。

sidecar-deployment.yaml を作成します。

cat > sidecar-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sidecar-worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sidecar-worker
  template:
    metadata:
      labels:
        app: sidecar-worker
    spec:
      terminationGracePeriodSeconds: 0
      volumes:
      - name: shared-logs
        emptyDir: {}
      containers:
      - name: app
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - 'i=1; while true; do echo "worker-line-${i}" >> /var/log/shared/worker.log; i=$((i+1)); sleep 2; done'
        volumeMounts:
        - name: shared-logs
          mountPath: /var/log/shared
      - name: log-sidecar
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - 'touch /var/log/shared/worker.log; tail -n +1 -f /var/log/shared/worker.log'
        volumeMounts:
        - name: shared-logs
          mountPath: /var/log/shared
EOF

Deployment を適用します。

kubectl apply -f sidecar-deployment.yaml

期待される出力:

deployment.apps/sidecar-worker created

Deployment が利用可能になるまで待ちます。

kubectl wait --for=condition=Available deployment/sidecar-worker --timeout=120s

期待される出力:

deployment.apps/sidecar-worker condition met

Deployment によって作成された Pod を見つけます。

worker_pod="$(kubectl get pods -l app=sidecar-worker -o 'jsonpath={.items[0].metadata.name}')"
echo "$worker_pod"

期待される出力には生成された Pod 名が表示されます。

sidecar-worker-...

Deployment によって作成された Pod からサイドカーのログを読み取ります。

kubectl logs "$worker_pod" -c log-sidecar --tail=3

期待される出力:

worker-line-...
worker-line-...
worker-line-...

まとめ

アプリコンテナとサイドカーコンテナを持つマルチコンテナ Pod を作成し、emptyDir ボリュームを使用してログファイルを共有し、両方のコンテナが一緒に動作することを確認しました。さらに、同じサイドカーパターンを Deployment テンプレートに移行しました。これで、サイドカーがいつ適しているか(アプリケーションの実行中にアプリケーションをサポートする場合)を理解できたはずです。