You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DevOps-Bash-tools/.bash.d/kubernetes.sh

291 lines
8.5 KiB
Bash

#!/usr/bin/env bash
# vim:ts=4:sts=4:sw=4:et
#
# Author: Hari Sekhon
# Date: 2019-07-28 14:56:41 +0100 (Sun, 28 Jul 2019)
#
# https://github.com/harisekhon/bash-tools
#
# License: see accompanying Hari Sekhon LICENSE file
#
# If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish
#
# https://www.linkedin.com/in/harisekhon
#
# ============================================================================ #
# K u b e r n e t e s / O p e n S h i f t
# ============================================================================ #
for x in kubectl oc; do
if type -P "$x" &>/dev/null; then
# shellcheck disable=SC1090
source <("$x" completion bash)
fi
done
# minishift oc-env > ~/.minishift.env
if [ -f ~/.minishift.env ]; then
# remove .minishift.env if it causes errors, which can happen if it was generated when there was no MiniShift VM running
# shellcheck disable=SC1090
. ~/.minishift.env || rm -f ~/.minishift.env
fi
#if [ -f "/usr/local/opt/kube-ps1/share/kube-ps1.sh" ]; then
# . "/usr/local/opt/kube-ps1/share/kube-ps1.sh"
# # overriden in prompt.sh which is evaluated later so this is sourced there
# #PS1='$(kube_ps1)'" $PS1"
#fi
# ============================================================================ #
# 'k8s-app' label is set by dashboard creation but who uses that
k8s_get_pod_opts="-o wide -L app,env"
alias po='k get po $k8s_get_pod_opts'
alias kapply='k apply -f'
alias kapp=kapply
alias wp=watchpods
alias ke=kubeexec
alias kg='k get'
alias ka='k apply'
alias kl='k logs'
alias kshell='kube-shell'
alias kubesh='kube-shell'
alias use="k config use-context"
alias contexts="k config get-contexts"
#alias context="k config current-context"
context(){ k config current-context; }
# contexts has this info and is more useful
#alias clusters="k config get-clusters"
alias kcd='k config set-context $(kubectl config current-context) --namespace'
alias menv='eval $(minikube docker-env)'
# ============================================================================ #
kubectl_opts="${KUBECTL_OPTS:-}"
# set K8S_NAMESPACE in local .bashrc or similar files for environments where your ~/.kube/config
# gets regenerated daily with certification authentication from a kerberos login script, which
# resets the 'kcd bigdata' namespace change. This way you automatically send the right namespace every time
if [ "${K8S_NAMESPACE:-}" ]; then
kubectl_opts="-n $K8S_NAMESPACE"
fi
# TODO: might split this later
oc_opts="$kubectl_opts"
# ============================================================================ #
# oc() and kubectl() fix future invocations of k() to the each command if you want to explicitly switch between them
oc(){
export KUBERNETES_CLI=oc
# shellcheck disable=SC2086
command oc $oc_opts "$@"
}
kubectl(){
export KUBERNETES_CLI=kubectl
# shellcheck disable=SC2086
command kubectl $kubectl_opts "$@"
}
k(){
local opts
# more efficient than forking to check history every time
if [ -n "$KUBERNETES_CLI" ]; then
case "$KUBERNETES_CLI" in
kubectl) opts="$kubectl_opts"
;;
oc) opts="$oc_opts"
;;
*) echo "invalid command '$KUBERNETES_CLI' listed in \$KUBERNETES_CLI (must be either 'kubectl' or 'oc' depending on whether you are using straight Kubernetes or OpenShift). Fix the variable or unset it to auto-detect when calling the k() function"
return
;;
esac
# shellcheck disable=SC2086
command "$KUBERNETES_CLI" $opts "$@"
else
# shellcheck disable=SC2086
case "$(k8s_or_openshift)" in
openshift) command oc $oc_opts "$@"
export KUBERNETES_CLI=oc
;;
k8s|*) command kubectl $kubectl_opts "$@"
export KUBERNETES_CLI=kubectl
;;
esac
fi
}
krun(){
local image="$1"
local name="${image//\//-}"
shift
# sleep infinity only works on some distros
k run --generator=run-pod/v1 "$name" --image "$image" -ti -- /bin/sh
}
kexec(){
local line
local name="${1//\//-}"
if [ -z "$name" ]; then
echo "usage: kexec <name>"
return 1
fi
for ((i=0;i<100;i++)); do
line="$(k get po | grep -F "$name")"
if [ -z "$line" ]; then
echo "No pod matching name $name found!"
return 1
fi
name="$(awk '/Running/{print $1}' <<< "$line")"
if [ -n "$name" ]; then
break
fi
echo "waiting for pod to start running..."
sleep 1
done
k exec -ti "$name" -- /bin/sh
}
# looks like both of these work on OpenShift context
#
# 'kubectl get pods'
#
# 'oc get pods'
# figure out if we're using k8s or openshift via most recent commands - return either 'k8s' or 'openshift'
k8s_or_openshift(){
local last_k8s_cmd
last_k8s_cmd="$(
history |
grep -v history |
grep -Eo -e '\<oc\>' \
-e '\<kubect[l]\>' \
-e '\<minikub[e]\>' \
-e '\<minishif[t]\>' |
tail -n 1
)"
case "$last_k8s_cmd" in
oc|minishift) echo openshift
# these end up in a subshell so aren't really useful, set in k() instead
#export KUBERNETES_CLI=oc
;;
kubectl|minikube) echo k8s
#export KUBERNETES_CLI=kubectl
;;
*) echo unknown
;;
esac
}
oc_get_pods(){
# shellcheck disable=SC2086
oc get pods $k8s_get_pod_opts
}
k8s_get_pods(){
# shellcheck disable=SC2086
k get pods $k8s_get_pod_opts
}
get_pods(){
#case "$(k8s_or_openshift)" in
# openshift) oc_get_pods
# ;;
# k8s) k8s_get_pods
# ;;
# *) k8s_get_pods
# ;;
#esac
#
# k8s functions now include k8s vs oc detection, no need for above or would end up double calling k8s_or_openshift
k8s_get_pods
}
export -f get_pods
get_pod(){
local filter="${1:-.*}"
get_pods |
grep -v '^NAME[[:space:]]' |
grep Running |
awk "/$filter/{print \$1; exit}"
}
watchpods(){
# watch on Mac (brew installed) doesn't have -x switch and doesn't work on even 'export -f function'
# leave using kubectl call for now as that works on openshift too
watch "
echo 'Context: '
echo
kubectl config current-context
echo
echo
echo 'Pods:'
echo
kubectl $kubectl_opts get pods $k8s_get_pod_opts 2>&1
echo
"
}
kdesc(){
k describe "$@"
}
kdp(){
kdesc pods "$@"
}
kdelp(){
k delete pod "$@"
}
kubeexec(){
local pod
pod="$(get_pod "$1")"
shift
k exec -ti "$pod" "$@" /bin/sh
}
# Getting token works on stock Kubernetes but not OpenShift due to stricter defaults
#
# Error from server (Forbidden): secrets is forbidden: User "developer" cannot list secrets in the namespace "kube-system": no RBAC policy matched
# error: resource name may not be empty
#
## even after 'oc login' as system/admin
#
# Error from server (Forbidden): secrets is forbidden: User "system" cannot list secrets in the namespace "kube-system": no RBAC policy matched
# error: resource name may not be empty
#
k8s_get_token(){
kubectl describe secret -n kube-system \
"$(kubectl get secrets -n kube-system | grep default | cut -f1 -d ' ')" |
grep '^token' |
awk '{print $2}'
}
k8s_get_api(){
local context
local cluster
context="$(context)"
cluster="$(k config view -o jsonpath="{.contexts[?(@.name == \"$context\")].context.cluster}")"
k config view -o jsonpath="{.clusters[?(@.name == \"$cluster\")].cluster.server}"
# or if you have jq installed:
# k get --raw=/api | jq -r '.serverAddressByClientCIDRs[0].serverAddress'
echo
}
# run kubectl commands against multiple clusters
kclusters(){
for context in $(kubectl config get-contexts -o=name --kubeconfig clusters.yaml); do
kubectl "$@" --kubeconfig clusters.yaml --context="$context"
done
}
# to kubectl apply manifests to both clusters for multi-cluster deployments
kclustersapply(){
kclusters apply -f "$@" # eg. manifests
}