KubectlコマンドによるKubernetes管理のDevOps実践

Tech

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

KubectlコマンドによるKubernetes管理のDevOps実践

要件と前提

DevOpsにおいてKubernetesの管理は、単なる手動操作ではなく、自動化され、再現性があり、安全なプロセスとして構築されるべきです。本稿では、kubectl コマンドを核に、jqcurl といったツールを組み合わせ、systemd を用いた自動化の例を提示します。

前提条件:

  • Kubernetesクラスターが利用可能であること (Minikube, Kind, GKE, EKS, AKSなど)。

  • クライアント環境に kubectl, jq, curl がインストールされていること。

  • systemd を利用可能なLinux環境であること。

  • sudo 権限を持つユーザー、または systemd サービスを管理できる権限。

  • root権限の扱いと権限分離の原則:

    • Kubernetesへのアクセスは、最小権限の原則に基づき、必要な権限のみを持つService Accountやユーザーを使用すべきです。

    • kubectl コマンドを実行するスクリプト自体は、可能な限り非rootユーザーで実行されるべきです。

    • systemd サービスとして実行する場合も、専用の非rootユーザーとグループを設定し、ProtectSystem=truePrivateTmp=true などを用いてセキュリティを強化します。

    • KUBECONFIG 環境変数や -kubeconfig オプションを使って、個別のクレデンシャルファイルを指定することで、権限分離をさらに徹底できます。

実装

DevOpsの自動化スクリプトは、冪等性(idempotent)を保ち、エラーハンドリングを適切に行うことが不可欠です。

1. 安全なBashスクリプトのフレームワーク

#!/usr/bin/env bash


# Strict mode: Exit immediately if a command exits with a non-zero status.


# Exit immediately if a pipeline command fails.


# Treat unset variables as an error when substituting.

set -euo pipefail

# Function to clean up temporary directory upon script exit or error

_cleanup() {
    if [ -n "${TMP_DIR:-}" ] && [ -d "${TMP_DIR}" ]; then
        echo "INFO: Cleaning up temporary directory: ${TMP_DIR}" >&2
        rm -rf "${TMP_DIR}"
    fi
}

# Register the cleanup function to be executed on EXIT (normal exit) or ERR (error exit)

trap '_cleanup' EXIT ERR

# Create a unique temporary directory

TMP_DIR=$(mktemp -d)
echo "INFO: Using temporary directory: ${TMP_DIR}" >&2

# --- ここに実際の処理を記述 ---


# 例: Kubernetesマニフェストファイルを一時ディレクトリに作成し適用

MANIFEST_FILE="${TMP_DIR}/nginx-deployment.yaml"

cat <<EOF > "${MANIFEST_FILE}"
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-example
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:

      - name: nginx
        image: nginx:1.14.2
        ports:

        - containerPort: 80
EOF

echo "INFO: Applying Kubernetes manifest: ${MANIFEST_FILE}" >&2
kubectl apply -f "${MANIFEST_FILE}"

echo "INFO: Waiting for deployment 'nginx-example' to be ready..." >&2
kubectl rollout status deployment/nginx-example --timeout=300s

echo "SUCCESS: Deployment 'nginx-example' is ready." >&2

# --- 処理終わり ---

2. jq を用いたKubernetesリソースのJSON処理

kubectl get -o json で取得したJSON出力を jq でパースし、必要な情報を抽出します。

#!/usr/bin/env bash

set -euo pipefail

# ... (trap, TMP_DIR の設定は上記と同様に含める) ...

NAMESPACE="default"
DEPLOYMENT_NAME="nginx-example" # 前のステップで作成したデプロイメント

echo "INFO: Fetching pod information for deployment '${DEPLOYMENT_NAME}' in namespace '${NAMESPACE}'..." >&2

# 1. Running状態のPod名とIPアドレスを抽出

kubectl get pods -n "${NAMESPACE}" -l app=nginx -o json | \
    jq -r '.items[] | select(.status.phase == "Running") | "\(.metadata.name) (\(.status.podIP))"' || {
        echo "ERROR: Failed to retrieve or parse pod information." >&2
        exit 1
    }

echo "INFO: Fetching container images for deployment '${DEPLOYMENT_NAME}'..." >&2

# 2. デプロイメントが使用しているコンテナイメージ名を抽出

kubectl get deployment "${DEPLOYMENT_NAME}" -n "${NAMESPACE}" -o json | \
    jq -r '.spec.template.spec.containers[].image' || {
        echo "ERROR: Failed to retrieve or parse deployment container images." >&2
        exit 1
    }

echo "SUCCESS: Successfully extracted Kubernetes resource information." >&2

3. curl を用いたAPI連携(TLS/再試行/バックオフ)

kubectl proxy を利用してローカルプロキシを立て、Kubernetes APIに curl でアクセスする例です。本番環境では、適切な認証情報(Service Accountトークンなど)とTLS証明書検証が必要です。

#!/usr/bin/env bash

set -euo pipefail

# ... (trap, TMP_DIR の設定は上記と同様に含める) ...

# Ensure kubectl proxy is running in a background process


# In a real scenario, you'd use a secure KUBECONFIG with appropriate RBAC.


# For demonstration, we'll start a proxy and clean it up.

echo "INFO: Starting kubectl proxy in background..." >&2
kubectl proxy --port=8001 > /dev/null 2>&1 &
PROXY_PID=$!

# Ensure proxy is killed on script exit

trap "kill ${PROXY_PID} || true; _cleanup" EXIT ERR

# Wait for proxy to be ready

echo "INFO: Waiting for kubectl proxy to be ready..." >&2
sleep 3 # Give it a few seconds to start

API_SERVER="http://localhost:8001"
NAMESPACE="default"
MAX_RETRIES=5
INITIAL_RETRY_INTERVAL=2 # seconds

_get_pods_via_api_with_retry() {
    local url="${API_SERVER}/api/v1/namespaces/${NAMESPACE}/pods"
    local attempt=0
    local current_retry_interval="${INITIAL_RETRY_INTERVAL}"

    while true; do
        echo "INFO: Attempt $((attempt + 1)): Fetching pods from ${url}..." >&2

        # --fail: HTTPステータスコードが400以上の場合に失敗


        # --insecure: TLS証明書の検証をスキップ (開発/テスト用, 本番では非推奨)


        # --max-time: 最大実行時間

        response=$(curl --silent --show-error --fail --insecure --max-time 10 "${url}")

        if [ $? -eq 0 ]; then
            echo "${response}"
            return 0
        else
            echo "WARNING: Curl failed on attempt $((attempt + 1)). Error: $response" >&2
        fi

        attempt=$((attempt + 1))
        if [ "${attempt}" -ge "${MAX_RETRIES}" ]; then
            echo "ERROR: Failed to fetch pods after ${MAX_RETRIES} attempts." >&2
            return 1
        fi

        echo "INFO: Retrying in ${current_retry_interval} seconds (exponential backoff)..." >&2
        sleep "${current_retry_interval}"
        current_retry_interval=$((current_retry_interval * 2)) # Exponential backoff
        if [ "${current_retry_interval}" -gt 30 ]; then # Cap max retry interval
            current_retry_interval=30
        fi
    done
}

echo "INFO: Calling Kubernetes API via curl..." >&2
_get_pods_via_api_with_retry | jq -r '.items[].metadata.name' || {
    echo "ERROR: Failed to get or parse pods via API." >&2
    exit 1
}

echo "SUCCESS: Successfully fetched pods via Kubernetes API." >&2

検証

デプロイメントが意図通りに動作しているかを確認します。

#!/usr/bin/env bash

set -euo pipefail

# ... (trap, TMP_DIR の設定は上記と同様に含める) ...

DEPLOYMENT_NAME="nginx-example"
NAMESPACE="default"

echo "INFO: Verifying deployment status for '${DEPLOYMENT_NAME}'..." >&2

# 1. デプロイメントのロールアウトステータスを確認

kubectl rollout status deployment/${DEPLOYMENT_NAME} -n "${NAMESPACE}" --timeout=120s || {
    echo "ERROR: Deployment '${DEPLOYMENT_NAME}' did not become ready." >&2
    exit 1
}

echo "INFO: Describing deployment '${DEPLOYMENT_NAME}' to check events and status..." >&2

# 2. 詳細情報を取得 (イベントやコンディションを確認)

kubectl describe deployment "${DEPLOYMENT_NAME}" -n "${NAMESPACE}"

echo "INFO: Checking logs of a pod in deployment '${DEPLOYMENT_NAME}'..." >&2

# 3. Podのログを確認 (最初のRunning Podのログを取得)

POD_NAME=$(kubectl get pods -n "${NAMESPACE}" -l app=nginx -o json | \
           jq -r '.items[] | select(.status.phase == "Running") | .metadata.name' | head -n 1)

if [ -z "${POD_NAME}" ]; then
    echo "WARNING: No running pods found for deployment '${DEPLOYMENT_NAME}' to check logs." >&2
else
    echo "INFO: Fetching logs for pod '${POD_NAME}'..." >&2
    kubectl logs "${POD_NAME}" -n "${NAMESPACE}"
fi

echo "SUCCESS: Deployment verification complete." >&2

運用

Kubernetesリソースの定期的な監視や管理タスクには systemd unit/timer が非常に有効です。

1. 監視スクリプトの作成

systemd から実行される監視スクリプトは、必要な情報のみをログに出力し、エラー時には適切なステータスコードを返すように設計します。

/usr/local/bin/monitor_kubernetes_pods.sh

#!/usr/bin/env bash

set -euo pipefail

# KUBECONFIGパスを指定することで、systemdサービスに特定のkubeconfigを適用できる


# 例: KUBECONFIG=/etc/kubernetes/systemd-monitor-kubeconfig.yaml


# ここではデフォルトの~/.kube/configを使用


# export KUBECONFIG="/etc/kubernetes/monitor_kubeconfig"

# Get non-running pods, exclude completed jobs (e.g., cronjobs)

NOT_RUNNING_PODS=$(kubectl get pods --field-selector=status.phase!=Running -o json 2>/dev/null | \
                   jq -r '.items[] | select(.status.phase != "Succeeded") | .metadata.name')

if [ -n "${NOT_RUNNING_PODS}" ]; then

    # systemd-cat を使用してjournaldにログを出力

    echo "WARNING: Non-running pods detected: ${NOT_RUNNING_PODS}" | systemd-cat -t kubernetes-monitor -p warning
    exit 1 # Non-zero exit code indicates an issue
else
    echo "INFO: All application pods are running." | systemd-cat -t kubernetes-monitor -p info
    exit 0 # Zero exit code indicates success
fi

sudo chmod +x /usr/local/bin/monitor_kubernetes_pods.sh で実行権限を付与します。 権限分離の注意点: このスクリプトがアクセスする kubeconfig は、get pods の最小限の権限を持つService Accountのトークンを使用するよう、RBACを設定することが重要です。

2. systemd Unitファイルの作成

/etc/systemd/system/kubernetes-monitor.service

[Unit]
Description=Kubernetes Pod Status Monitor
Documentation=https://example.com/kubernetes-monitor-doc

# ネットワークが利用可能になってからサービスを開始

Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/monitor_kubernetes_pods.sh

# サービス実行ユーザーとグループを指定 (非rootユーザーが推奨)


# 必要に応じて、専用のユーザー/グループを作成:


# sudo useradd -r -s /bin/false kubernetes-monitor-user


# User=kubernetes-monitor-user


# Group=kubernetes-monitor-group

# セキュリティ強化設定

ProtectSystem=full      # /usr, /boot などのシステムディレクトリをリードオンリーにマウント
ProtectHome=true        # /home, /root ディレクトリへのアクセスを禁止
PrivateTmp=true         # サービス専用の/tmpと/var/tmpを作成
NoNewPrivileges=true    # 子プロセスが追加の特権を取得することを禁止

# 必要に応じて環境変数 (例: KUBECONFIG) を設定


# Environment="KUBECONFIG=/etc/kubernetes/systemd-monitor-kubeconfig.yaml"

# エラー時の再起動ポリシー


# OnFailure: 失敗した場合にのみ再起動


# OnSuccess: 成功した場合にのみ再起動


# Always: 終了コードに関わらず常に再起動


# Restart=on-failure


# RestartSec=5s

# ログ出力制限


# StandardOutput=journal


# StandardError=journal

[Install]
WantedBy=multi-user.target

3. systemd Timerファイルの作成

/etc/systemd/system/kubernetes-monitor.timer

[Unit]
Description=Run Kubernetes Pod Status Monitor every 5 minutes

[Timer]

# システム起動から1分後に初めて実行

OnBootSec=1min

# サービスがアクティブになってから5分後に次の実行をスケジュール

OnUnitActiveSec=5min

# サービスファイルを指定

Unit=kubernetes-monitor.service

[Install]
WantedBy=timers.target

4. systemd サービスとタイマーの有効化・起動・ログ確認

sudo 権限が必要です。

# 1. systemdデーモンをリロードして新しいユニットファイルを認識させる

sudo systemctl daemon-reload

# 2. タイマーを有効化 (システム起動時に自動開始されるようにする)

sudo systemctl enable kubernetes-monitor.timer

# 3. タイマーを今すぐ起動

sudo systemctl start kubernetes-monitor.timer

# 4. タイマーのステータスを確認

systemctl status kubernetes-monitor.timer

# 5. サービスの実行ログを確認 (systemd-catで出力されたログがjournaldに記録される)

journalctl -u kubernetes-monitor.service --since "10 minutes ago"

# (任意) 必要に応じて、手動でサービスを実行してテスト


# sudo systemctl start kubernetes-monitor.service

トラブルシュート

Kubernetes環境での問題解決には、各種ツールの連携が重要です。

  • kubectl コマンド:

    • kubectl get events: クラスタ全体のイベント履歴を確認し、問題の発生源を特定します。

    • kubectl describe <resource_type>/<name>: リソースの詳細な状態、関連イベント、コンディション、設定を確認します。

    • kubectl logs <pod_name>: 特定のPodのコンテナログをチェックします。-f でリアルタイム追跡、-p で以前のコンテナログ。

    • kubectl exec -it <pod_name> -- /bin/bash: Pod内でシェルを実行し、内部からデバッグします。

    • kubectl top pod/node: リソース使用率を監視し、ボトルネックを特定します。

  • curl デバッグ:

    • curl -v: 詳細なリクエスト/レスポンスヘッダ情報を表示します。

    • curl --trace-ascii debug.log: すべてのネットワーク通信をファイルに記録します。

  • systemd ログ:

    • journalctl -u kubernetes-monitor.service -f: systemd サービスによって生成されたログをリアルタイムで監視します。

    • journalctl -t kubernetes-monitor: systemd-cat -t kubernetes-monitor で指定したタグでログをフィルタリングします。

まとめ

、DevOpsエンジニアが kubectl を中心に、jqcurlsystemd を活用してKubernetesクラスターを効果的に管理するための実践的なアプローチを紹介しました。冪等性を保った安全なBashスクリプトの書き方から、JSON処理、API連携、そして systemd による自動監視まで、一連のワークフローをカバーしました。

特に、root権限の最小化権限分離の原則はDevOpsの重要な柱であり、systemd ユニットファイルのセキュリティ強化設定やKubernetesのRBACを適切に設定することで、より堅牢な運用環境を構築できます。これらのプラクティスを通じて、Kubernetesの管理作業を自動化し、安定性と効率性を向上させることが可能です。

graph TD
    A["DevOps Engineer"] --> |Initiates| B("Idempotent Bash Script");
    B --> |Create/Update Manifests| C{"Kubernetes API"};
    C --> |Apply/Validate| D[Kubectl];
    D --> |Resource Changes| E["Kubernetes Cluster"];
    B --> |Monitor Rollout Status| F("Kubectl Rollout Status");
    F --> |Confirmation| B;
    subgraph Automated Monitoring with Systemd
        G["Systemd Timer"] --> |Triggers Periodically| H("Monitor Script");
        H --> |Check K8s Status("get -o json")| D;
        D --> |Return JSON Data| H;
        H --> |Process with JQ| I["Log/Alert Service"];
        I --> |Notify/Store Alerts| A;
    end
    E --> |Resource State| D;
    click A "https://kubernetes.io/docs/concepts/security/rbac-good-practices/" "Best Practices for RBAC"
    click B "https://kubernetes.io/docs/reference/kubectl/overview/" "kubectl Overview"
ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました