OpenShift & K8S Cheat Sheet: Difference between revisions

From Bitbull Wiki
Jump to navigation Jump to search
No edit summary
 
(63 intermediate revisions by the same user not shown)
Line 1: Line 1:
=Kubernetes=
=Kubernetes=
==Setup==
===oc===
mkdir $HOME/bin ; cd $HOME/bin
curl -L https://github.com/$(curl -L -s https://github.com/openshift/okd/releases | grep  openshift-client-linux- | head -1 | cut -d\" -f2) --output openshift-client-linux.tar.gz
tar vxfz openshift-client-linux.tar.gz
rm -f openshift-client-linux.tar.gz README.md
===kubectl-neat===
mkdir $HOME/bin ; cd $HOME/bin
rm -f kubectl-neat
wget https://github.com/itaysk/kubectl-neat/releases/latest/download/kubectl-neat_linux_amd64.tar.gz
chmod 700 kubectl-neat
tar vxfz kubectl-neat_linux_amd64.tar.gz
rm -f LICENSE kubectl-neat_linux_amd64.tar.gz
===kubectl===
mkdir $HOME/bin ; cd $HOME/bin
rm -f kubectl
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod 700 kubectl
grep 'kubectl completion bash' $HOME/.bashrc || echo 'source <(kubectl completion bash)' >> $HOME/.bashrc
===kustomize===
cd $HOME/bin
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"  | bash
===helm===
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | sh
grep 'helm completion bash' $HOME/.bashrc || echo 'source <(helm completion bash)' >> $HOME/.bashrc
==Daily==
==Daily==
  * https://kubernetes.io/de/docs/reference/kubectl/cheatsheet/
  * https://kubernetes.io/de/docs/reference/kubectl/cheatsheet/


===SHELL==
===SHELL===
* Authenticate Kubectl
* Authenticate Kubectl
  export KUBECONFIG=<PATH-TO-M>-CONFIG>/kubeconfig-dev.yaml
  export KUBECONFIG=<PATH-TO-CONFIG>/kubeconfig-dev.yaml


==.bash_profile==
===Use Helm===
* openshift project/user prompt
* https://artifacthub.io/
* https://hub.helm.sm/
* https://hub.kubeapps.com/
 
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml # for K3S
helm search hub wordpress --max-col-width 120
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
 
===Install APP with Helm===
kubectl create namespace wordpress
kubectl config set-context --current --namespace=wordpress
helm install my-wordpress bitnami/wordpress
 
kubectl get all
 
kubectl delete service my-wordpress
kubectl get pods
kubectl exec my-wordpress-55dc589b4c-ldkxj -- printenv | grep HTTP
kubectl expose deployment/my-wordpress --port=8080 --name=my-wordpress
kubectl get service
 
kubectl create ingress ingress-www --rule=wp.vm20.test.domain.ch/*=my-wordpress:8080
 
firefox https://wp.vm20.test.domain.ch/login
# User: user
# Password: $(kubectl get secret --namespace wordpress my-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)
helm delete my-wordpress
kubectl delete namespace wordpress
 
 
 
[[Category:Linux]]
[[Category:OpenShift & K8S]]
[[Category:ReferenceCards]]
 
 
 
[[Category:Linux]]
[[Category:OpenShift & K8S]]
[[Category:ReferenceCards]]
 
 
 
[[Category:Linux]]
[[Category:OpenShift & K8S]]
[[Category:ReferenceCards]]
 
===.bashrc===
* kubectl helpers
<pre>
<pre>
source <(kubectl completion bash)
source <(kubectl completion bash)
export PS1='### \D{%d.%m.%Y_%H:%M} \u@\h:\w \e[1;33m✯\e[m $(kubectl config view -o jsonpath="{.contexts[].context.namespace}") \n# '
export PS1="# \$(kubectl config view -o jsonpath="{.contexts[].context.namespace}") $PS1"
alias kn='kubectl get ns'
alias kp='kubectl get pods'
alias ka='kubectl get all'
alias kpvc='kubectl get pvc'
alias kpv='kubectl get pv'
 
_knd_complete() {
    local curr_arg="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(kubectl get namespaces --no-headers -o custom-columns=":metadata.name" | grep "^$curr_arg") )
}
 
knd() {
    if [[ -n "$1" ]]; then
        kubectl config set-context --current --namespace="$1"
    else
        echo "Usage: knd <namespace>"
        echo "Available namespaces:"
        kubectl get namespaces --no-headers -o custom-columns=":metadata.name"
    fi
}
 
complete -F _knd_complete knd
 
kpvcc() {
    # Prompt for user input with defaults
    read -p "Name [pvc1]: " pvc_name
    pvc_name=${pvc_name:-pvc1}
    read -p "Access Modes [ReadWriteOnce]: " access_modes
    access_modes=${access_modes:-ReadWriteOnce}
    read -p "Storage [5Gi]: " storage
    storage=${storage:-5Gi}
    # Apply the PVC using inline YAML
    kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $pvc_name
spec:
  accessModes:
    - $access_modes
  resources:
    requests:
      storage: $storage
  storageClassName: local-path
EOF
 
    echo "PVC '$pvc_name' created with AccessModes='$access_modes' and Storage='$storage'"
}
 
</pre>
</pre>


* password gen
 
 
 
 
==Deploy==
===Create Secret===
<pre>
<pre>
genpasswd() {
username=myuser
  local l=$1
read password
  [ "$l" == "" ] && l=16
 
  tr -dc A-Za-z0-9_=., < /dev/urandom | head -c ${l} | xargs
kubectl create secret generic db-user-pass --from-literal=username=$username --from-literal=password="$password"
}
 
kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode
 
----REF IN POD------
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: db-user-pass
            key: username
</pre>
</pre>


==Deploy==
 
 
 
 
===Create and change into Namespace===
===Create and change into Namespace===
  kubectl create namespace mynamespace
  kubectl create namespace mynamespace
Line 51: Line 206:
===Create Ingress Rule for Service===
===Create Ingress Rule for Service===
  kubectl create ingress ingress-www --rule=www.domain.com/*=nginx-service:8080
  kubectl create ingress ingress-www --rule=www.domain.com/*=nginx-service:8080
===Docker Pull Secret===
oc create secret docker-registry docker --docker-server=docker.io --docker-username=username1 --docker-email=chris@domain.ch --docker-password=xcgsedfgsdfhgsdfg
oc secrets link default docker --for=pull
oc new-app --name wiki --image image.registry.tld/image:tag --source-secret=docker
==Change/Update==
===Force Deployment to pull (latest)===
oc get deployments
oc set env deployment/myapp UPDATE_TIMESTAMP="$(date)"
oc rollout status deployment/myapp
oc describe pod [POD_NAME]


==Configure==
==Configure==
===Traefik Config===
- https://levelup.gitconnected.com/a-guide-to-k3s-ingress-using-traefik-with-nodeport-6eb29add0b4b
kubectl edit deployments traefik -n kube-system
kubectl -n kube-system edit cm traefik


==Debug==
==Debug==
===Run Container with custom Command===
===Run Container with custom Command===
  kubectl run -i --tty busybox --image=busybox -- sh
  kubectl run -i --tty busybox --image=busybox -- sh
===Attach Container in Pod===
===Attach Container in Pod (log)===
kubectl attach busybox -c busybox -i -t
kubectl attach busybox -c busybox -i -t
 
===Jump into Pods Shell===
kubectl exec --stdin --tty shell-demo -- /bin/bash
 
===Get all Containers on all Namespaces===
kubectl get pods --all-namespaces -o jsonpath="{..image}" |tr -s '[[:space:]]' '\n' |sort |uniq -c


===Get all Containers grouped by Pods for all Namespaces===
kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |sort




Line 65: Line 252:




===Open Firewall for NodePort (non persistent)===
kubectl describe svc | grep NodePort: | awk '{print $3}' | tr 'A-Z' 'a-z' | grep -v '^$' | while read PORT
do
  echo PORT=$PORT
  firewall-cmd --zone=public --add-port=$PORT
done




=Helpers=
==.bash_profile==


* openshift project/user prompt
 
 
=OpenShift=
==Install==
 
===OC & KUBECTL (OKD)===
mkdir $HOME/bin ; cd $HOME/bin
rm -f oc
wget https://github.com/$(curl -L https://github.com/openshift/okd/releases/latest/ | grep openshift-client-linux | grep href= | cut -d\" -f2 )
tar vxfz openshift-client-linux-*.tar.gz
rm -rf README.md openshift-client-linux-*.tar.gz
grep 'oc completion bash' $HOME/.bashrc || echo 'source <(oc completion bash)' >> $HOME/.bashrc
grep 'kubectl completion bash' $HOME/.bashrc || echo 'source <(kubectl completion bash)' >> $HOME/.bashrc
 
 
 
 
 
===OC & KUBECTL (OpenShift)===
mkdir $HOME/bin ; cd $HOME/bin
rm -f oc kubectl
wget https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz
tar vxfz oc.tar.gz
rm -f README.md oc.tar.gz
grep 'oc completion bash' $HOME/.bashrc || echo 'source <(oc completion bash)' >> $HOME/.bashrc
grep 'kubectl completion bash' $HOME/.bashrc || echo 'source <(kubectl completion bash)' >> $HOME/.bashrc
 
 
 
 
 
===.bashrc===
<pre>
<pre>
function ps1(){
genpasswd() {
   export PS1='[\u@\h($(oc whoami -c 2>/dev/null|cut -d/ -f3,1)) \W]\$ '
   local l=$1
  [ "$l" == "" ] && l=16
  tr -dc A-Za-z0-9_=., < /dev/urandom | head -c ${l} | xargs
}
}
function ps1e(){
 
  export PS1='# [\d \t \u@\h($(oc whoami -c 2>/dev/null|cut -d/ -f3,1)) \W]\n$ '
source <(kubectl completion bash)
export PS1="# \$(kubectl config view -o jsonpath="{.contexts[].context.namespace}") $PS1"
 
_knd_complete() {
    local curr_arg="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(kubectl get namespaces --no-headers -o custom-columns=":metadata.name" | grep "^$curr_arg") )
}
 
knd() {
    if [[ -n "$1" ]]; then
        kubectl config set-context --current --namespace="$1"
    else
        echo "Usage: knd <namespace>"
        echo "Available namespaces:"
        kubectl get namespaces --no-headers -o custom-columns=":metadata.name"
    fi
}
 
complete -F _knd_complete knd
 
alias knl='kubectl get ns'
alias kp='kubectl get pods'
alias ka='kubectl get all'
alias kpvc='kubectl get pvc'
alias kpv='kubectl get pv'
 
kpvcc() {
    # Prompt for user input with defaults
    read -p "Name [pvc1]: " pvc_name
    pvc_name=${pvc_name:-pvc1}
 
    read -p "Access Modes [ReadWriteOnce]: " access_modes
    access_modes=${access_modes:-ReadWriteOnce}
 
    read -p "Storage [5Gi]: " storage
    storage=${storage:-5Gi}
 
    # Apply the PVC using inline YAML
    kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $pvc_name
spec:
  accessModes:
    - $access_modes
  resources:
    requests:
      storage: $storage
  storageClassName: standard
EOF
 
    echo "PVC '$pvc_name' created with AccessModes='$access_modes' and Storage='$storage'"
}
}
</pre>
</pre>


* password gen
 
<pre>
 
genpasswd() {
 
        local l=$1
 
        [ "$l" == "" ] && l=16
==Debug==
        tr -dc A-Za-z0-9_=%.,: < /dev/urandom | head -c ${l} | xargs
===etcd===
  }
M1=$(oc get nodes -l node-role.kubernetes.io/master  | grep Ready | head -1 | cut -d' ' -f1 )
</pre>
oc rsh -n openshift-etcd etcd-$M1  <<EOF                                       
  etcdctl member list -w table
EOF




Line 116: Line 394:




==backup all openshift objects in all projects ==
<pre>
oc get all --all-namespaces --no-headers=true | awk '{print $1","$2}' | while read obj
do
  NS=$(echo $obj | cut -d, -f1)
  OBJ=$(echo $obj | cut -d, -f2)
  FILE=$(echo $obj | sed 's/\//-/g;s/,/-/g')
  echo $NS $OBJ $FILE; oc export -n $NS $OBJ -o yaml > $FILE.yml
done
</pre>


==backup all kubernets objects in current namespace ==
 
<pre>
 
oc get projects
 
oc project my-namespace
 
kubectl get all --no-headers=true | awk '{print $1}' | while read obj
 
do
 
  OBJ=$(echo $obj | cut -d, -f2)
 
  FILE=$(echo $obj | sed 's/\//-/g;s/,/-/g')
 
  echo " ------------- $NS $OBJ $FILE"
 
  kubectl get $OBJ -o yaml > $FILE.yml
 
done
</pre>


=snippets=
=snippets=
Line 213: Line 479:


=database backup=
=database backup=
==mariadb (os v3.9)==
==mariadb==
* install global backup template
* install global backup template
  oc create -f https://raw.githubusercontent.com/joe-speedboat/mariadb-backup-cronjob/master/mariadb-backup-template.yaml
  oc create -f https://raw.githubusercontent.com/joe-speedboat/openshift.mariadb-backup-cronjob/master/mariadb-backup-template_okd410.yaml
* more information can be found on git repo [https://github.com/joe-speedboat/mariadb-backup-cronjob mariadb-backup-cronjob]
* more information can be found on git repo [https://github.com/joe-speedboat/mariadb-backup-cronjob mariadb-backup-cronjob]
==mariadb database backup with oc==
oc rsh dc/mariadb /bin/sh -i -c "MYSQL_PWD=$MYSQL_ROOT_PASSWORD /usr/bin/mysqldump -u root --skip-lock-tables \$MYSQL_DATABASE" > mysqldb.sql
oc rsh deployments/mariadb /bin/bash -i -c "MYSQL_PWD=\$MARIADB_ROOT_PASSWORD /usr/bin/mysqldump -u root --skip-lock-tables \$MYSQL_DATABASE" > mariadb.sql
==postgresql dump with kubectl==
kubectl exec zammad-postgresql-0 -- bash -c "PGPASSWORD="xxx" pg_dump -Uzammad zammad_production" > zammad_production.sql


=Maintenance=
=Maintenance=
==Databases==
===Mariadb login===
MYSQL_PWD="$MARIADB_ROOT_PASSWORD" mysql -u root $MYSQL_DATABASE
===mysql login===
  mysql -u $MYSQL_USER -p"$MYSQL_PASSWORD" $MYSQL_DATABASE
[[Category:Linux]]
[[Category:OpenShift & K8S]]
[[Category:ReferenceCards]]
==CleanUp old docker images on nodes==
==CleanUp old docker images on nodes==
: Keeping up to three tag revisions 1, and keeping resources (images, image streams and pods) younger than sixty minutes:
: Keeping up to three tag revisions 1, and keeping resources (images, image streams and pods) younger than sixty minutes:

Latest revision as of 12:22, 4 February 2025

Kubernetes

Setup

oc

mkdir $HOME/bin ; cd $HOME/bin 
curl -L https://github.com/$(curl -L -s https://github.com/openshift/okd/releases | grep  openshift-client-linux- | head -1 | cut -d\" -f2) --output openshift-client-linux.tar.gz
tar vxfz openshift-client-linux.tar.gz
rm -f openshift-client-linux.tar.gz README.md

kubectl-neat

mkdir $HOME/bin ; cd $HOME/bin 
rm -f kubectl-neat
wget https://github.com/itaysk/kubectl-neat/releases/latest/download/kubectl-neat_linux_amd64.tar.gz
chmod 700 kubectl-neat
tar vxfz kubectl-neat_linux_amd64.tar.gz
rm -f LICENSE kubectl-neat_linux_amd64.tar.gz

kubectl

mkdir $HOME/bin ; cd $HOME/bin 
rm -f kubectl
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod 700 kubectl
grep 'kubectl completion bash' $HOME/.bashrc || echo 'source <(kubectl completion bash)' >> $HOME/.bashrc

kustomize

cd $HOME/bin
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"  | bash



helm

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | sh
grep 'helm completion bash' $HOME/.bashrc || echo 'source <(helm completion bash)' >> $HOME/.bashrc



Daily

* https://kubernetes.io/de/docs/reference/kubectl/cheatsheet/

SHELL

  • Authenticate Kubectl
export KUBECONFIG=<PATH-TO-CONFIG>/kubeconfig-dev.yaml

Use Helm

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml # for K3S
helm search hub wordpress --max-col-width 120
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

Install APP with Helm

kubectl create namespace wordpress
kubectl config set-context --current --namespace=wordpress
helm install my-wordpress bitnami/wordpress
kubectl get all
kubectl delete service my-wordpress
kubectl get pods
kubectl exec my-wordpress-55dc589b4c-ldkxj -- printenv | grep HTTP
kubectl expose deployment/my-wordpress --port=8080 --name=my-wordpress
kubectl get service
kubectl create ingress ingress-www --rule=wp.vm20.test.domain.ch/*=my-wordpress:8080
firefox https://wp.vm20.test.domain.ch/login
# User: user
# Password: $(kubectl get secret --namespace wordpress my-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)

helm delete my-wordpress
kubectl delete namespace wordpress

.bashrc

  • kubectl helpers
source <(kubectl completion bash)
export PS1="# \$(kubectl config view -o jsonpath="{.contexts[].context.namespace}") $PS1"
alias kn='kubectl get ns'
alias kp='kubectl get pods'
alias ka='kubectl get all'
alias kpvc='kubectl get pvc'
alias kpv='kubectl get pv'

_knd_complete() {
    local curr_arg="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(kubectl get namespaces --no-headers -o custom-columns=":metadata.name" | grep "^$curr_arg") )
}

knd() {
    if [[ -n "$1" ]]; then
        kubectl config set-context --current --namespace="$1"
    else
        echo "Usage: knd <namespace>"
        echo "Available namespaces:"
        kubectl get namespaces --no-headers -o custom-columns=":metadata.name"
    fi
}

complete -F _knd_complete knd

kpvcc() {
    # Prompt for user input with defaults
    read -p "Name [pvc1]: " pvc_name
    pvc_name=${pvc_name:-pvc1}
    read -p "Access Modes [ReadWriteOnce]: " access_modes
    access_modes=${access_modes:-ReadWriteOnce}
    read -p "Storage [5Gi]: " storage
    storage=${storage:-5Gi}
    # Apply the PVC using inline YAML
    kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $pvc_name
spec:
  accessModes:
    - $access_modes
  resources:
    requests:
      storage: $storage
  storageClassName: local-path
EOF

    echo "PVC '$pvc_name' created with AccessModes='$access_modes' and Storage='$storage'"
}



Deploy

Create Secret

username=myuser
read password

kubectl create secret generic db-user-pass --from-literal=username=$username --from-literal=password="$password"

kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode

----REF IN POD------
    env:
       - name: SECRET_USERNAME
         valueFrom:
           secretKeyRef:
             name: db-user-pass
             key: username



Create and change into Namespace

kubectl create namespace mynamespace
kubectl config set-context --current --namespace=mynamespace

Deploy Docker Container and Expose Service

kubectl create deployment xfce --image=christian773/xfce-vnc:latest --port=6901

Inject VARS into Deployment/Container

kubectl edit deployment nginx1
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
    env:
    - name: MY_VAT
      value: MY_VALUE

Get Environment VARS of Pod

kubectl exec pod-name -- printenv

Expose Container Port as Service

kubectl expose deployment nginx-app --port=8080 --name=nginx-service

Create Ingress Rule for Service

kubectl create ingress ingress-www --rule=www.domain.com/*=nginx-service:8080

Docker Pull Secret

oc create secret docker-registry docker --docker-server=docker.io --docker-username=username1 --docker-email=chris@domain.ch --docker-password=xcgsedfgsdfhgsdfg
oc secrets link default docker --for=pull
oc new-app --name wiki --image image.registry.tld/image:tag --source-secret=docker

Change/Update

Force Deployment to pull (latest)

oc get deployments
oc set env deployment/myapp UPDATE_TIMESTAMP="$(date)"
oc rollout status deployment/myapp
oc describe pod [POD_NAME]



Configure

Traefik Config

- https://levelup.gitconnected.com/a-guide-to-k3s-ingress-using-traefik-with-nodeport-6eb29add0b4b

kubectl edit deployments traefik -n kube-system
kubectl -n kube-system edit cm traefik



Debug

Run Container with custom Command

kubectl run -i --tty busybox --image=busybox -- sh

Attach Container in Pod (log)

kubectl attach busybox -c busybox -i -t

Jump into Pods Shell

kubectl exec --stdin --tty shell-demo -- /bin/bash

Get all Containers on all Namespaces

kubectl get pods --all-namespaces -o jsonpath="{..image}" |tr -s 'space:' '\n' |sort |uniq -c

Get all Containers grouped by Pods for all Namespaces

kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |sort



Open Firewall for NodePort (non persistent)

kubectl describe svc | grep NodePort: | awk '{print $3}' | tr 'A-Z' 'a-z' | grep -v '^$' | while read PORT
do
  echo PORT=$PORT
  firewall-cmd --zone=public --add-port=$PORT
done



OpenShift

Install

OC & KUBECTL (OKD)

mkdir $HOME/bin ; cd $HOME/bin 
rm -f oc
wget https://github.com/$(curl -L https://github.com/openshift/okd/releases/latest/ | grep openshift-client-linux | grep href= | cut -d\" -f2 )
tar vxfz openshift-client-linux-*.tar.gz
rm -rf README.md openshift-client-linux-*.tar.gz
grep 'oc completion bash' $HOME/.bashrc || echo 'source <(oc completion bash)' >> $HOME/.bashrc
grep 'kubectl completion bash' $HOME/.bashrc || echo 'source <(kubectl completion bash)' >> $HOME/.bashrc



OC & KUBECTL (OpenShift)

mkdir $HOME/bin ; cd $HOME/bin 
rm -f oc kubectl
wget https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz
tar vxfz oc.tar.gz 
rm -f README.md oc.tar.gz
grep 'oc completion bash' $HOME/.bashrc || echo 'source <(oc completion bash)' >> $HOME/.bashrc
grep 'kubectl completion bash' $HOME/.bashrc || echo 'source <(kubectl completion bash)' >> $HOME/.bashrc



.bashrc

genpasswd() {
   local l=$1
   [ "$l" == "" ] && l=16
   tr -dc A-Za-z0-9_=., < /dev/urandom | head -c ${l} | xargs
}

source <(kubectl completion bash)
export PS1="# \$(kubectl config view -o jsonpath="{.contexts[].context.namespace}") $PS1"

_knd_complete() {
    local curr_arg="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(kubectl get namespaces --no-headers -o custom-columns=":metadata.name" | grep "^$curr_arg") )
}

knd() {
    if [[ -n "$1" ]]; then
        kubectl config set-context --current --namespace="$1"
    else
        echo "Usage: knd <namespace>"
        echo "Available namespaces:"
        kubectl get namespaces --no-headers -o custom-columns=":metadata.name"
    fi
}

complete -F _knd_complete knd

alias knl='kubectl get ns'
alias kp='kubectl get pods'
alias ka='kubectl get all'
alias kpvc='kubectl get pvc'
alias kpv='kubectl get pv'

kpvcc() {
    # Prompt for user input with defaults
    read -p "Name [pvc1]: " pvc_name
    pvc_name=${pvc_name:-pvc1}

    read -p "Access Modes [ReadWriteOnce]: " access_modes
    access_modes=${access_modes:-ReadWriteOnce}

    read -p "Storage [5Gi]: " storage
    storage=${storage:-5Gi}

    # Apply the PVC using inline YAML
    kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $pvc_name
spec:
  accessModes:
    - $access_modes
  resources:
    requests:
      storage: $storage
  storageClassName: standard
EOF

    echo "PVC '$pvc_name' created with AccessModes='$access_modes' and Storage='$storage'"
}



Debug

etcd

M1=$(oc get nodes -l node-role.kubernetes.io/master  | grep Ready | head -1 | cut -d' ' -f1 )
oc rsh -n openshift-etcd etcd-$M1  <<EOF                                        
etcdctl member list -w table
EOF



Administration

daily cmds

oc get nodes -o wide
oc get all -o wide --all-namespaces
oc get ep -o wide
oc get events --sort-by='.lastTimestamp'
oc get rolebindings --all-namespaces
oc get pv
oc get pvc
oc get projects
oc get users
oc get groups

inspect user/group permissions

oc get rolebinding -o wide -n gitea
oc get rolebinding -o wide --all-namespaces

inspect imagestreams

oc get is -n openshift
oc describe is php -n openshift
oc export -n openshift isimage php@42c4a9072f








snippets

run as root (anyuid)

oc create serviceaccount sa-anyuid
oc adm policy add-scc-to-user anyuid -z sa-anyuid
# create new-app before to get a dc
oc patch dc/deployment-config-name --patch '{"spec":{"template":{"spec":{"serviceAccountName": "sa-anyuid"}}}}'

run as root (anyuid) for every pod in project

oc adm policy add-scc-to-user anyuid -z default

imagestream demo (build service)

  • get all the imagestreams
oc get is -n openshift
  • inspect nginx imagestream
oc describe is nginx -n openshift
  • setup new project
oc new-project is-demo
  • setup the dev environment
oc new-app --name=html-dev  nginx:1.10~https://github.com/joe-speedboat/openshift.html.devops.git#master
oc get all
oc logs -f builds/html-dev-1
oc get svc
oc expose svc/html-dev --hostname=html-dev.app.domain.com
oc get route
curl http://html-dev.app.domain.com
  • show this app to the qa team
oc get is
oc tag docker-registry.default.svc:5000/is-demo/html-dev:latest is-demo/html-qa:1.0
oc get is
oc new-app --name=html-qa --image-stream="is-demo/html-qa:1.0"
oc expose svc/html-qa --hostname=html-qa.app.domain.com
curl html-qa.app.domain.com
  • now go and make some changes to the git repo, then push it to github
now lets build the latest dev release
oc start-build html-dev
oc status
oc get pods
  • check dev application for latest changes
curl http://html-dev.app.domain.com
  • check if qa application remains in desired state
curl html-qa.app.domain.com
  • now commit the new dev branch to qa branch
oc get is
oc tag docker-registry.default.svc:5000/is-demo/html-dev html-qa:1.1
  • change the imagestream to newer release
oc edit dc/html-qa
oc get dc
oc get pods
  • check if qa application is reflecting latest changes from v1.1
curl html-qa.app.domain.com
  • now we rollback the qa release to v1.0
oc edit dc/html-qa
oc get dc
oc get pods
  • check if qa application is reflecting the rollbacked version v1.0
curl html-qa.app.domain.com

database backup

mariadb

  • install global backup template
oc create -f https://raw.githubusercontent.com/joe-speedboat/openshift.mariadb-backup-cronjob/master/mariadb-backup-template_okd410.yaml



mariadb database backup with oc

oc rsh dc/mariadb /bin/sh -i -c "MYSQL_PWD=$MYSQL_ROOT_PASSWORD /usr/bin/mysqldump -u root --skip-lock-tables \$MYSQL_DATABASE" > mysqldb.sql
oc rsh deployments/mariadb /bin/bash -i -c "MYSQL_PWD=\$MARIADB_ROOT_PASSWORD /usr/bin/mysqldump -u root --skip-lock-tables \$MYSQL_DATABASE" > mariadb.sql



postgresql dump with kubectl

kubectl exec zammad-postgresql-0 -- bash -c "PGPASSWORD="xxx" pg_dump -Uzammad zammad_production" > zammad_production.sql



Maintenance

Databases

Mariadb login

MYSQL_PWD="$MARIADB_ROOT_PASSWORD" mysql -u root $MYSQL_DATABASE

mysql login

 mysql -u $MYSQL_USER -p"$MYSQL_PASSWORD" $MYSQL_DATABASE

CleanUp old docker images on nodes

Keeping up to three tag revisions 1, and keeping resources (images, image streams and pods) younger than sixty minutes:
oc adm prune images --keep-tag-revisions=3 --keep-younger-than=60m
Pruning every image that exceeds defined limits:
oc adm prune images --prune-over-size-limit
CopyPaste example
oc adm prune images --keep-tag-revisions=3 --keep-younger-than=60m --confirm
oc adm prune images --prune-over-size-limit --confirm