本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
KubectlコマンドによるKubernetes管理のDevOps実践
要件と前提
DevOpsにおいてKubernetesの管理は、単なる手動操作ではなく、自動化され、再現性があり、安全なプロセスとして構築されるべきです。本稿では、kubectl コマンドを核に、jq、curl といったツールを組み合わせ、systemd を用いた自動化の例を提示します。
前提条件:
Kubernetesクラスターが利用可能であること (Minikube, Kind, GKE, EKS, AKSなど)。
クライアント環境に
kubectl,jq,curlがインストールされていること。systemdを利用可能なLinux環境であること。sudo権限を持つユーザー、またはsystemdサービスを管理できる権限。root権限の扱いと権限分離の原則:
Kubernetesへのアクセスは、最小権限の原則に基づき、必要な権限のみを持つService Accountやユーザーを使用すべきです。
kubectlコマンドを実行するスクリプト自体は、可能な限り非rootユーザーで実行されるべきです。systemdサービスとして実行する場合も、専用の非rootユーザーとグループを設定し、ProtectSystem=trueやPrivateTmp=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 を中心に、jq、curl、systemd を活用して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"


コメント