Check Liveness Probe Configuration for Deployment order¶
What does it do?
This script is a Bash script that validates the configuration of probes in a Kubernetes deployment manifest. It checks if the ports used in the probe configurations are exposed by the containers and offers recommendations for next steps if any issues are found.
#!/bin/bash# Set deployment name and namespacePROBE_TYPE="${1:-readinessProbe}"# Default to livenessProbe, can be set to readinessProbe# Function to extract data using jq
extract_data(){echo"$1"|jq-r"$2"2>/dev/null# jq used to extract data in JSON format}# Function to extract port from command
extract_port_from_command(){echo"$1"|grep-oE':[0-9]+'|grep-oE'[0-9]+'|head-n1# regex used to extract ports}# Get deployment manifest in JSON formatMANIFEST=$(${KUBERNETES_DISTRIBUTION_BINARY}getdeployment"$DEPLOYMENT_NAME"-n"$NAMESPACE"--context"$CONTEXT"-ojson)# Fetching deployment details using kubernetes distribution binary if[$?-ne0];then# Check if error occurred while fetching deployment detailsecho"Error fetching deployment details: $MANIFEST"exit1fi# Get number of containersNUM_CONTAINERS=$(extract_data"$MANIFEST"'.spec.template.spec.containers | length')# Extracting number of containersif[-z"$NUM_CONTAINERS"];then# Check if no containers foundecho"No containers found in deployment."exit1finext_steps=()# Initialize empty array for next steps# Loop through containers and validate probesfor((i=0;i<NUM_CONTAINERS;i++));doPROBE=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].${PROBE_TYPE}")# Extracting type of probe for each containerCONTAINER_NAME=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].name")# Extracting container nameecho"-------- START Validation - Container Name: $CONTAINER_NAME Probe Type: $PROBE_TYPE -------"echo"Container: \`$CONTAINER_NAME\`"echo"$PROBE_TYPE: $PROBE"# List container portsCONTAINER_PORTS=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].ports[].containerPort")# Extracting exposed ports for the containerif[-n"$CONTAINER_PORTS"];thenecho"Exposed Ports: $CONTAINER_PORTS"else:
echo"No ports exposed."fiif[-z"$PROBE"];then# Check if probe not found for containerecho"Container \`$CONTAINER_NAME\`: ${PROBE_TYPE} not found."continuefi# Validate that the port in the probe is defined in the container's portsifecho"$PROBE"|jq-e'.httpGet, .tcpSocket'>/dev/null;then# Check if HTTP GET or TCP Socket presentPROBE_PORT=$(extract_data"$PROBE"'.httpGet.port // .tcpSocket.port')# Extracting port for probeCONTAINER_PORTS=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].ports[].containerPort")# Extracting container portsif[[!" $CONTAINER_PORTS "==*"$PROBE_PORT"*]];then# Check if probe port exists in container portsecho"Container \`$CONTAINER_NAME\`: Port $PROBE_PORT used in $PROBE_TYPE is not exposed by the container."next_steps+=("Update $PROBE_TYPE For \`${DEPLOYMENT_NAME}\` to use one of the following ports: $CONTAINER_PORTS")else:
echo"Container \`$CONTAINER_NAME\`: ${PROBE_TYPE} port $PROBE_PORT is valid."fifi# Check if exec permissions are available (for exec type probes)ifecho"$PROBE"|jq-e'.exec'>/dev/null;then# Check if exec existsIFS=$'\n'read-r-d''-aEXEC_COMMAND_ARRAY<<(echo"$PROBE"|jq-r'.exec.command[]'&&printf'\0')# Extracting exec commandPORT_IN_COMMAND=$(extract_port_from_command"${EXEC_COMMAND_ARRAY[*]}")# Extracting port from exec command# Check if we see the port in the exec command, and if so, if it's defined in the manifestif[-n"$PORT_IN_COMMAND"];then# Check if port exists in exec commandCONTAINER_PORTS=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].ports[].containerPort")# Extracting container portsif[[!" $CONTAINER_PORTS "==*"$PORT_IN_COMMAND"*]];then# Check if port exists in container portsecho"Container \`$CONTAINER_NAME\`: Port $PORT_IN_COMMAND used in ${PROBE_TYPE} exec command is not exposed by the container. The following ports are exposed: $CONTAINER_PORTS"next_steps+=("Get Deployment Workload Details For \`$DEPLOYMENT_NAME\`")next_steps+=("Remediate Readiness and Liveness Probes for Deployments in Namespace \`${NAMESPACE}\`")else:
echo"Container \`$CONTAINER_NAME\`: Port $PORT_IN_COMMAND in ${PROBE_TYPE} exec command is valid."fifi# Check exec permission and execute commandif${KUBERNETES_DISTRIBUTION_BINARY}authcan-icreatepods/exec-n"$NAMESPACE">/dev/null2>&1;then# Check exec permissions# Execute command# ...# ... (more code to execute command and test ports)elseecho"Exec permission is not available."fifiecho"------- END Validation - Container Name: $CONTAINER_NAME Probe Type: $PROBE_TYPE -------"done# Display all unique recommendations that can be shown as Next Stepsif[[${#next_steps[@]}-ne0]];then# Check if there are any next stepsprintf"\nRecommended Next Steps: \n"printf"%s\n""${next_steps[@]}"|sort-u# Print unique next stepsfi
Check Readiness Probe Configuration for Deployment order¶
What does it do?
This script is a Bash script that validates the configuration of probes in a Kubernetes deployment manifest. It checks if the ports used in the probe configurations are exposed by the containers and offers recommendations for next steps if any issues are found.
#!/bin/bash# Set deployment name and namespacePROBE_TYPE="${1:-readinessProbe}"# Default to livenessProbe, can be set to readinessProbe# Function to extract data using jq
extract_data(){echo"$1"|jq-r"$2"2>/dev/null# jq used to extract data in JSON format}# Function to extract port from command
extract_port_from_command(){echo"$1"|grep-oE':[0-9]+'|grep-oE'[0-9]+'|head-n1# regex used to extract ports}# Get deployment manifest in JSON formatMANIFEST=$(${KUBERNETES_DISTRIBUTION_BINARY}getdeployment"$DEPLOYMENT_NAME"-n"$NAMESPACE"--context"$CONTEXT"-ojson)# Fetching deployment details using kubernetes distribution binary if[$?-ne0];then# Check if error occurred while fetching deployment detailsecho"Error fetching deployment details: $MANIFEST"exit1fi# Get number of containersNUM_CONTAINERS=$(extract_data"$MANIFEST"'.spec.template.spec.containers | length')# Extracting number of containersif[-z"$NUM_CONTAINERS"];then# Check if no containers foundecho"No containers found in deployment."exit1finext_steps=()# Initialize empty array for next steps# Loop through containers and validate probesfor((i=0;i<NUM_CONTAINERS;i++));doPROBE=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].${PROBE_TYPE}")# Extracting type of probe for each containerCONTAINER_NAME=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].name")# Extracting container nameecho"-------- START Validation - Container Name: $CONTAINER_NAME Probe Type: $PROBE_TYPE -------"echo"Container: \`$CONTAINER_NAME\`"echo"$PROBE_TYPE: $PROBE"# List container portsCONTAINER_PORTS=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].ports[].containerPort")# Extracting exposed ports for the containerif[-n"$CONTAINER_PORTS"];thenecho"Exposed Ports: $CONTAINER_PORTS"else:
echo"No ports exposed."fiif[-z"$PROBE"];then# Check if probe not found for containerecho"Container \`$CONTAINER_NAME\`: ${PROBE_TYPE} not found."continuefi# Validate that the port in the probe is defined in the container's portsifecho"$PROBE"|jq-e'.httpGet, .tcpSocket'>/dev/null;then# Check if HTTP GET or TCP Socket presentPROBE_PORT=$(extract_data"$PROBE"'.httpGet.port // .tcpSocket.port')# Extracting port for probeCONTAINER_PORTS=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].ports[].containerPort")# Extracting container portsif[[!" $CONTAINER_PORTS "==*"$PROBE_PORT"*]];then# Check if probe port exists in container portsecho"Container \`$CONTAINER_NAME\`: Port $PROBE_PORT used in $PROBE_TYPE is not exposed by the container."next_steps+=("Update $PROBE_TYPE For \`${DEPLOYMENT_NAME}\` to use one of the following ports: $CONTAINER_PORTS")else:
echo"Container \`$CONTAINER_NAME\`: ${PROBE_TYPE} port $PROBE_PORT is valid."fifi# Check if exec permissions are available (for exec type probes)ifecho"$PROBE"|jq-e'.exec'>/dev/null;then# Check if exec existsIFS=$'\n'read-r-d''-aEXEC_COMMAND_ARRAY<<(echo"$PROBE"|jq-r'.exec.command[]'&&printf'\0')# Extracting exec commandPORT_IN_COMMAND=$(extract_port_from_command"${EXEC_COMMAND_ARRAY[*]}")# Extracting port from exec command# Check if we see the port in the exec command, and if so, if it's defined in the manifestif[-n"$PORT_IN_COMMAND"];then# Check if port exists in exec commandCONTAINER_PORTS=$(extract_data"$MANIFEST"".spec.template.spec.containers[$i].ports[].containerPort")# Extracting container portsif[[!" $CONTAINER_PORTS "==*"$PORT_IN_COMMAND"*]];then# Check if port exists in container portsecho"Container \`$CONTAINER_NAME\`: Port $PORT_IN_COMMAND used in ${PROBE_TYPE} exec command is not exposed by the container. The following ports are exposed: $CONTAINER_PORTS"next_steps+=("Get Deployment Workload Details For \`$DEPLOYMENT_NAME\`")next_steps+=("Remediate Readiness and Liveness Probes for Deployments in Namespace \`${NAMESPACE}\`")else:
echo"Container \`$CONTAINER_NAME\`: Port $PORT_IN_COMMAND in ${PROBE_TYPE} exec command is valid."fifi# Check exec permission and execute commandif${KUBERNETES_DISTRIBUTION_BINARY}authcan-icreatepods/exec-n"$NAMESPACE">/dev/null2>&1;then# Check exec permissions# Execute command# ...# ... (more code to execute command and test ports)elseecho"Exec permission is not available."fifiecho"------- END Validation - Container Name: $CONTAINER_NAME Probe Type: $PROBE_TYPE -------"done# Display all unique recommendations that can be shown as Next Stepsif[[${#next_steps[@]}-ne0]];then# Check if there are any next stepsprintf"\nRecommended Next Steps: \n"printf"%s\n""${next_steps[@]}"|sort-u# Print unique next stepsfi
This command is using kubectl to get events from a specific context and namespace in JSON format, then filtering the results to show only warnings related to Deployments, ReplicaSets, or Pods with a specific name within the last hour. The output is grouped by kind and name, showing the count, unique reasons, unique messages, first and last timestamps of the warning events.
This multi-line content is auto-generated and used for educational purposes. Copying and pasting the multi-line text might not function as expected.
# Get events from a Kubernetes cluster in a specific context and namespace in JSON formatkubectlgetevents --context ${CONTEXT} -n ${NAMESPACE} -ojson | \
# Use jq to filter and format the datajq'# Define a time limit based on 1 hour ago(now - (60*60)) as $time_limit |# Filter and map items based on certain conditions[ .items[] |# Select only Warning events related to Deployment, ReplicaSet, or Podselect(.type == "Warning" and (.involvedObject.kind == "Deployment" or .involvedObject.kind == "ReplicaSet" or .involvedObject.kind == "Pod") and# Make sure the name contains the given deployment name (.involvedObject.name | tostring | contains("${DEPLOYMENT_NAME}")) and# Check if lastTimestamp is more recent than the time limit (.lastTimestamp | fromdateiso8601) >= $time_limit) |# Create a new object with selected properties{kind: .involvedObject.kind, name: .involvedObject.name, reason: .reason, message: .message, firstTimestamp: .firstTimestamp, lastTimestamp: .lastTimestamp} ] |# Group the objects by kind and namegroup_by([.kind, .name]) |# Map the grouped objects into a desired formatmap({kind: .[0].kind, name: .[0].name, count: length, reasons: map(.reason) | unique, messages: map(.message) | unique, firstTimestamp: map(.firstTimestamp | fromdateiso8601) | sort | .[0] | todateiso8601, lastTimestamp: map(.lastTimestamp | fromdateiso8601) | sort | reverse | .[0] | todateiso8601})'
Get Deployment Workload Details For order and Add to Report¶
What does it do?
This command is used to retrieve the YAML configuration for a specific deployment in a Kubernetes cluster, specified by the deployment name, context, and namespace. It's a way to view the detailed configuration settings for that deployment.
Command
kubectl get deployment/order --context gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster -n acme-fitness -o yaml
This command retrieves information about a specific deployment from the Kubernetes cluster, including the number of desired, ready, missing, and unavailable replicas, as well as the available and progressing conditions. It uses jq to filter and format the information in JSON output.
This multi-line content is auto-generated and used for educational purposes. Copying and pasting the multi-line text might not function as expected.
# Set variables for the deployment name, context, and namespaceDEPLOYMENT_NAME=my-deploymentCONTEXT=my-contextNAMESPACE=my-namespace# Retrieve details about the specified deployment in JSON format, use 'jq' to parse the informationkubectlgetdeployment/${DEPLOYMENT_NAME}--context${CONTEXT}-n${NAMESPACE}-ojson|\
jq'.status | {desired_replicas:.replicas,ready_replicas:(.readyReplicas//0),missing_replicas:((.replicas//0)-(.readyReplicas//0)),unavailable_replicas:(.unavailableReplicas//0),available_condition:(ifany(.conditions[];.type=="Available")then(.conditions[]|select(.type=="Available"))else"Condition not available"end),progressing_condition:(ifany(.conditions[];.type=="Progressing")then(.conditions[]|select(.type=="Progressing"))else"Condition not available"end)}'
This script is using a bash shell to retrieve Kubernetes events in JSON format, processing and filtering the data using jq, and then outputting the processed events. It's likely used for monitoring and analyzing events related to Kubernetes deployments, replica sets, and pods.
This script is designed to manage ReplicaSets in Kubernetes deployments by checking for multiple ReplicaSets, verifying the active latest ReplicaSet, and providing actionable insights for any inactive or conflicting ReplicaSets during normal operations and rolling updates. It uses a series of checks and operations involving JSON data obtained from the Kubernetes cluster.
#!/bin/bash# Kubernetes Deployment ReplicaSet Management Script# This script checks Kubernetes deployments to ensure they are running the latest ReplicaSet. It is designed to manage# ReplicaSets during normal operations and rolling updates, checking for multiple ReplicaSets, verifying the active latest ReplicaSet, and providing actionable insights for any inactive or conflicting ReplicaSets.# Function to check for rolling update status
check_rolling_update_status(){# Extract conditions and replica countslocalprogressingCondition=$(echo"$DEPLOYMENT_JSON"|jq'.status.conditions[] | select(.type=="Progressing")')localavailableCondition=$(echo"$DEPLOYMENT_JSON"|jq'.status.conditions[] | select(.type=="Available").status')localreplicas=$(echo"$DEPLOYMENT_JSON"|jq'.status.replicas // 0')localupdatedReplicas=$(echo"$DEPLOYMENT_JSON"|jq'.status.updatedReplicas // 0')localavailableReplicas=$(echo"$DEPLOYMENT_JSON"|jq'.status.availableReplicas // 0')localreadyReplicas=$(echo"$DEPLOYMENT_JSON"|jq'.status.readyReplicas // 0')# Interpret 'Progressing' condition more accuratelylocalprogressingStatus=$(echo"$progressingCondition"|jq-r'.status')localprogressingReason=$(echo"$progressingCondition"|jq-r'.reason')locallastUpdateTime=$(echo"$progressingCondition"|jq-r'.lastUpdateTime')# Current time in UTC for comparison (assuming 'date' command is available and system timezone is correctly set)localcurrentTime=$(date-u+"%Y-%m-%dT%H:%M:%SZ")# Compare replica counts for a more accurate ongoing rollout checkif[["$progressingStatus"=="True"&&"$progressingReason"=="NewReplicaSetAvailable"&&"$updatedReplicas"=="$replicas"&&"$availableReplicas"=="$updatedReplicas"&&"$readyReplicas"=="$updatedReplicas"]];then# Check how recent the last update was to consider a buffer for stabilizationif[[$(date-d"$lastUpdateTime"+%s)-lt$(date-d"$currentTime"+%s--date='-2 minutes')]];thenecho"Deployment $DEPLOYMENT_NAME is stable. No active rollout detected."ROLLING_UPDATE_STATUS=1# Indicates no update is in progresselseecho"Deployment $DEPLOYMENT_NAME has recently updated and may still be stabilizing."ROLLING_UPDATE_STATUS=0# Indicates recent update, considering stabilizationfielif[["$updatedReplicas"-lt"$replicas"]]||[["$availableReplicas"-lt"$updatedReplicas"]]||[["$readyReplicas"-lt"$updatedReplicas"]];thenecho"Deployment $DEPLOYMENT_NAME is undergoing a rollout."ROLLING_UPDATE_STATUS=0# Indicates an update is in progresselseecho"Deployment $DEPLOYMENT_NAME is stable. No active rollout detected."ROLLING_UPDATE_STATUS=1# Indicates no update is in progressfi}
verify_pods_association_with_latest_rs(){# Fetch all pods associated with the deploymentPODS_JSON=$(${KUBERNETES_DISTRIBUTION_BINARY}getpods-n$NAMESPACE--context$CONTEXT--selector=app=$DEPLOYMENT_NAME--context$CONTEXT-ojson)PODS_COUNT=$(echo"$PODS_JSON"|jq'.items | length')OUTDATED_PODS_COUNT=0for((i=0;i<PODS_COUNT;i++));doPOD_RS=$(echo"$PODS_JSON"|jq-r".items[$i].metadata.ownerReferences[] | select(.kind == \"ReplicaSet\") | .name")if[["$POD_RS"!="$LATEST_RS"]];thenOUTDATED_PODS_COUNT=$((OUTDATED_PODS_COUNT+1))fidoneif[["$OUTDATED_PODS_COUNT"-eq0]];thenecho"All pods are correctly associated with the latest ReplicaSet."elseecho"Warning: $OUTDATED_PODS_COUNT pod(s) are not associated with the latest ReplicaSet."issue_details="{\"severity\":\"2\",\"title\":\"$OUTDATED_PODS_COUNT pod(s) are not running the latest version of Deployment \`$DEPLOYMENT_NAME\` in namespace \`${NAMESPACE}\`\",\"next_steps\":\"Clean up stale ReplicaSet \`$RS\` for Deployment \`$DEPLOYMENT_NAME\` in namespace \`${NAMESPACE}\` \",\"details\":\"$RS_DETAILS\"}"fi}# Get Deployment JSONDEPLOYMENT_JSON=$(${KUBERNETES_DISTRIBUTION_BINARY}getdeployment$DEPLOYMENT_NAME-n$NAMESPACE--context$CONTEXT-ojson)# Get the deployment's latest ReplicaSetREPLICASETS_JSON=$(${KUBERNETES_DISTRIBUTION_BINARY}getrs-n$NAMESPACE--context$CONTEXT-ojson|jq--argDEPLOYMENT_NAME"$DEPLOYMENT_NAME"\'[.items[] | select(.metadata.ownerReferences[]? | select(.kind == "Deployment" and .name == $DEPLOYMENT_NAME))]')# Extract the name of the latest ReplicaSet from the filtered JSONLATEST_RS=$(echo"$REPLICASETS_JSON"|jq-r'sort_by(.metadata.creationTimestamp) | last(.[]).metadata.name')# Extract names of all ReplicaSets associated with the Deployment from the filtered JSONALL_RS=$(echo"$REPLICASETS_JSON"|jq-r'.[].metadata.name'|tr'\n'' ')
readarray-tALL_RS_NAMES<<(echo"$REPLICASETS_JSON"|jq-r'.[].metadata.name')echo"Latest ReplicaSet: $LATEST_RS"echo"All ReplicaSets for the deployment: $ALL_RS"ROLLING_UPDATE_STATUS=-1# Default to -1; will be set to 0 or 1 by check_rolling_update_status
check_rolling_update_status
# Check if there are multiple ReplicaSets and if the latest is activeif[[$(echo$ALL_RS|tr' ''\n'|wc-l)-gt1]];thenecho"Multiple ReplicaSets detected. Verifying..."# Loop through all ReplicaSetsforRSin$ALL_RS;do# Skip the latest ReplicaSetif[["$RS"=="$LATEST_RS"]];thencontinuefi# Check the status of older ReplicaSets (replicas, availableReplicas, readyReplicas)RS_DETAILS_JSON=$(echo"$REPLICASETS_JSON"|jq--argRS"$RS"'.[] | select(.metadata.name==$RS)')REPLICAS=$(echo"$RS_DETAILS_JSON"|jq'.status.replicas')if[["$REPLICAS"=="0"]];thenecho"ReplicaSet $RS for Deployment $DEPLOYMENT_NAME is not active. Consider for cleanup..."elseif[[$ROLLING_UPDATE_STATUS-eq0]];thendate
echo"Multiple ReplicaSets are active, which is expected due to the rolling update process."issue_details="{\"severity\":\"4\",\"title\":\"A rolling update is in progress for Deployment \`$DEPLOYMENT_NAME\` in namespace \`${NAMESPACE}\`\",\"next_steps\":\"Wait for Rollout to Complete and Check Again.\",\"details\":\"$RS_DETAILS\"}"elif[[$ROLLING_UPDATE_STATUS-eq1]];thenecho"Multiple ReplicaSets are active and no update appears to be in place. Investigation may be required to ensure they are not conflicting."verify_pods_association_with_latest_rs
issue_details="{\"severity\":\"2\",\"title\":\"Conflicting versions detected for Deployment \`$DEPLOYMENT_NAME\` in namespace \`${NAMESPACE}\`\",\"next_steps\":\"Clean up stale ReplicaSet \`$RS\` for Deployment \`$DEPLOYMENT_NAME\` in namespace \`${NAMESPACE}\` \",\"details\":\"$RS_DETAILS_JSON\"}"elseecho"Multiple ReplicaSets are active and no update appears to be in place. Investigation may be required to ensure they are not conflicting."fifi# Initialize issues as an empty array if not already setif[-z"$issues"];thenissues="[]"fi# Concatenate issue detail to the stringif[-n"$issue_details"];then# Remove the closing bracket from issues to prepare for adding a new itemissues="${issues%]}"# If issues is not an empty array (more than just "["), add a comma before the new itemif["$issues"!="["];thenissues="$issues,"fi# Add the new issue detail and close the arrayissues="$issues$issue_details]"fidoneelseecho"Only one ReplicaSet is active. Deployment is up to date."fi# Display all unique recommendations that can be shown as Next Stepsif[-n"$issues"];thenecho-e"\nRecommended Next Steps: \n"echo"$issues"fi