<p><!--META
{
"title": "KubectlコマンドによるKubernetes管理のDevOps実践",
"primary_category": "DevOps",
"secondary_categories": ["クラウド>Kubernetes","自動化","Infrastructure as Code"],
"tags": ["kubectl","Kubernetes","jq","curl","systemd","idempotent","bash"],
"summary": "DevOpsエンジニア向けにkubectlコマンドを用いたKubernetes管理を安全なbashスクリプト、jq/curl連携、systemd自動化で解説。",
"mermaid": true,
"verify_level": "L0",
"tweet_hint": {"text":"DevOpsエンジニアのためのKubectl活用ガイド!安全なbashスクリプト、jq/curl連携、systemdによるKubernetes自動管理を徹底解説。冪等性、権限分離、トラブルシュートまで網羅。 #Kubernetes #kubectl #DevOps","hashtags":["#Kubernetes","#kubectl","#DevOps"]},
"link_hints": ["https://kubernetes.io/docs/reference/kubectl/overview/","https://kubernetes.io/docs/concepts/security/rbac-good-practices/"]
}
-->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">KubectlコマンドによるKubernetes管理のDevOps実践</h1>
<h2 class="wp-block-heading">要件と前提</h2>
<p>DevOpsにおいてKubernetesの管理は、単なる手動操作ではなく、自動化され、再現性があり、安全なプロセスとして構築されるべきです。本稿では、<code>kubectl</code> コマンドを核に、<code>jq</code>、<code>curl</code> といったツールを組み合わせ、<code>systemd</code> を用いた自動化の例を提示します。</p>
<p><strong>前提条件:</strong></p>
<ul class="wp-block-list">
<li><p>Kubernetesクラスターが利用可能であること (Minikube, Kind, GKE, EKS, AKSなど)。</p></li>
<li><p>クライアント環境に <code>kubectl</code>, <code>jq</code>, <code>curl</code> がインストールされていること。</p></li>
<li><p><code>systemd</code> を利用可能なLinux環境であること。</p></li>
<li><p><code>sudo</code> 権限を持つユーザー、または <code>systemd</code> サービスを管理できる権限。</p></li>
<li><p><strong>root権限の扱いと権限分離の原則</strong>:</p>
<ul>
<li><p>Kubernetesへのアクセスは、最小権限の原則に基づき、必要な権限のみを持つService Accountやユーザーを使用すべきです。</p></li>
<li><p><code>kubectl</code> コマンドを実行するスクリプト自体は、可能な限り非rootユーザーで実行されるべきです。</p></li>
<li><p><code>systemd</code> サービスとして実行する場合も、専用の非rootユーザーとグループを設定し、<code>ProtectSystem=true</code> や <code>PrivateTmp=true</code> などを用いてセキュリティを強化します。</p></li>
<li><p><code>KUBECONFIG</code> 環境変数や <code>-kubeconfig</code> オプションを使って、個別のクレデンシャルファイルを指定することで、権限分離をさらに徹底できます。</p></li>
</ul></li>
</ul>
<h2 class="wp-block-heading">実装</h2>
<p>DevOpsの自動化スクリプトは、冪等性(idempotent)を保ち、エラーハンドリングを適切に行うことが不可欠です。</p>
<h3 class="wp-block-heading">1. 安全なBashスクリプトのフレームワーク</h3>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/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
# --- 処理終わり ---
</pre>
</div>
<h3 class="wp-block-heading">2. jq を用いたKubernetesリソースのJSON処理</h3>
<p><code>kubectl get -o json</code> で取得したJSON出力を <code>jq</code> でパースし、必要な情報を抽出します。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/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
</pre>
</div>
<h3 class="wp-block-heading">3. curl を用いたAPI連携(TLS/再試行/バックオフ)</h3>
<p><code>kubectl proxy</code> を利用してローカルプロキシを立て、Kubernetes APIに <code>curl</code> でアクセスする例です。本番環境では、適切な認証情報(Service Accountトークンなど)とTLS証明書検証が必要です。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/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
</pre>
</div>
<h2 class="wp-block-heading">検証</h2>
<p>デプロイメントが意図通りに動作しているかを確認します。</p>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/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
</pre>
</div>
<h2 class="wp-block-heading">運用</h2>
<p>Kubernetesリソースの定期的な監視や管理タスクには <code>systemd unit/timer</code> が非常に有効です。</p>
<h3 class="wp-block-heading">1. 監視スクリプトの作成</h3>
<p><code>systemd</code> から実行される監視スクリプトは、必要な情報のみをログに出力し、エラー時には適切なステータスコードを返すように設計します。</p>
<p><strong><code>/usr/local/bin/monitor_kubernetes_pods.sh</code></strong></p>
<div class="codehilite">
<pre data-enlighter-language="generic">#!/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
</pre>
</div>
<p><code>sudo chmod +x /usr/local/bin/monitor_kubernetes_pods.sh</code> で実行権限を付与します。
<strong>権限分離の注意点</strong>: このスクリプトがアクセスする <code>kubeconfig</code> は、<code>get pods</code> の最小限の権限を持つService Accountのトークンを使用するよう、RBACを設定することが重要です。</p>
<h3 class="wp-block-heading">2. systemd Unitファイルの作成</h3>
<p><strong><code>/etc/systemd/system/kubernetes-monitor.service</code></strong></p>
<div class="codehilite">
<pre data-enlighter-language="generic">[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
</pre>
</div>
<h3 class="wp-block-heading">3. systemd Timerファイルの作成</h3>
<p><strong><code>/etc/systemd/system/kubernetes-monitor.timer</code></strong></p>
<div class="codehilite">
<pre data-enlighter-language="generic">[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
</pre>
</div>
<h3 class="wp-block-heading">4. systemd サービスとタイマーの有効化・起動・ログ確認</h3>
<p><code>sudo</code> 権限が必要です。</p>
<div class="codehilite">
<pre data-enlighter-language="generic"># 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
</pre>
</div>
<h2 class="wp-block-heading">トラブルシュート</h2>
<p>Kubernetes環境での問題解決には、各種ツールの連携が重要です。</p>
<ul class="wp-block-list">
<li><p><strong><code>kubectl</code> コマンド</strong>:</p>
<ul>
<li><p><code>kubectl get events</code>: クラスタ全体のイベント履歴を確認し、問題の発生源を特定します。</p></li>
<li><p><code>kubectl describe <resource_type>/<name></code>: リソースの詳細な状態、関連イベント、コンディション、設定を確認します。</p></li>
<li><p><code>kubectl logs <pod_name></code>: 特定のPodのコンテナログをチェックします。<code>-f</code> でリアルタイム追跡、<code>-p</code> で以前のコンテナログ。</p></li>
<li><p><code>kubectl exec -it <pod_name> -- /bin/bash</code>: Pod内でシェルを実行し、内部からデバッグします。</p></li>
<li><p><code>kubectl top pod/node</code>: リソース使用率を監視し、ボトルネックを特定します。</p></li>
</ul></li>
<li><p><strong><code>curl</code> デバッグ</strong>:</p>
<ul>
<li><p><code>curl -v</code>: 詳細なリクエスト/レスポンスヘッダ情報を表示します。</p></li>
<li><p><code>curl --trace-ascii debug.log</code>: すべてのネットワーク通信をファイルに記録します。</p></li>
</ul></li>
<li><p><strong><code>systemd</code> ログ</strong>:</p>
<ul>
<li><p><code>journalctl -u kubernetes-monitor.service -f</code>: <code>systemd</code> サービスによって生成されたログをリアルタイムで監視します。</p></li>
<li><p><code>journalctl -t kubernetes-monitor</code>: <code>systemd-cat -t kubernetes-monitor</code> で指定したタグでログをフィルタリングします。</p></li>
</ul></li>
</ul>
<h2 class="wp-block-heading">まとめ</h2>
<p>、DevOpsエンジニアが <code>kubectl</code> を中心に、<code>jq</code>、<code>curl</code>、<code>systemd</code> を活用してKubernetesクラスターを効果的に管理するための実践的なアプローチを紹介しました。冪等性を保った安全なBashスクリプトの書き方から、JSON処理、API連携、そして <code>systemd</code> による自動監視まで、一連のワークフローをカバーしました。</p>
<p>特に、<strong>root権限の最小化</strong>と<strong>権限分離の原則</strong>はDevOpsの重要な柱であり、<code>systemd</code> ユニットファイルのセキュリティ強化設定やKubernetesのRBACを適切に設定することで、より堅牢な運用環境を構築できます。これらのプラクティスを通じて、Kubernetesの管理作業を自動化し、安定性と効率性を向上させることが可能です。</p>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
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"
</pre></div>
本記事は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
デバッグ:
systemd
ログ:
まとめ
、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"
コメント