linux|shell脚本|有趣的知识---格式化输出日志和脚本调试方法以及kubernetes集群核心服务重启和集群证书备份脚本

简介: linux|shell脚本|有趣的知识---格式化输出日志和脚本调试方法以及kubernetes集群核心服务重启和集群证书备份脚本

前言:

shell脚本的功能十分强大,这一点毋庸置疑的。那么,平常的工作中总是免不了和脚本打交道,也免不了要自己编写一些脚本。

每个人都希望自己编写的脚本强壮,简单,易用,功能多,并且总是希望脚本运行后不是一片黑白,色彩单调,无趣,而是有着整齐的,让人赏心悦目的输出日志。

OK,希望总是美好的嘛,但,如何实现也是有一定的技巧的,并不是你想实现就实现的哦。

那么,如何能够快速的提高shell编程的能力呢?

俗话说:师夷长技以制夷   这句话用在shell脚本编程方面同样的正确。在遇到一些shell脚本的时候,我们不应该是只是把这个脚本跑起来,然后看看结果正确了吗?然后就OK了。

正如某些优秀的编程人员一样,有着阅读源码的好习惯,经常的阅读一些优秀的shell脚本,并且能够解析这些优秀的shell脚本如何运作的,长此以往,shell编程的能力会如同我一样优秀,对吗?

好了,废话说了一堆,现在就隆重介绍一下github上的一个脚本。

此脚本是kubernetes集群更新证书用脚本,也就是说功能比较单一:将某个kubernetes集群的所有证书(或者某个组件的证书)延期到十年,并且在更新证书的同时给所有证书(或者某个组件的证书)做一个备份。

下载地址如下:

git clone https://github.com/yuyicai/update-kube-cert.git
cd update-kubeadm-cert
chmod 755 update-kubeadm-cert.sh

一,

脚本日志格式化输出

首先,我们定义了四种颜色,并定义了三种日志输出函数,分别是error,info,warning,最后只调用了log::info函数和check_file函数。

#!/usr/bin/env bash
#!author zsk
set -o errexit
set -o pipefail
# set -o xtrace
# set output color
NC='\033[0m'
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
log::err() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${RED}ERROR${NC}] %b\n" "$@"
}
log::info() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${GREEN}INFO] %b\n" "$@"
}
log::warning() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${YELLOW}WARNING${NC}] \033[0m%b\n" "$@"
}
check_file() {
  if [[ ! -r ${1} ]]; then
    log::err "can not find ${1}"
    exit 1
  fi
}
log::info "${GREEN}updated !!!${NC}"

那么,此脚本的输出是这样的:

输出了脚本执行时间和日志等级

OK,根据以上脚本,改造一个收集服务器信息的脚本,此脚本见我的博客:Linux运维小技巧---每日收集所有服务器信息并归档到指定服务器_晚风_END的博客-CSDN博客_linux运维 日活量怎么提取

改造后的脚本如下:

#!/bin/bash
#!author zsk
#description:system_info
NC='\033[0m'
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
log::err() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${RED}ERROR${NC}] %b\n" "$@"
}
log::info() {
  printf "[${GREEN}$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${YELLOW}INFO]${NC} %b\n" "$*"
}
log::warning() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${YELLOW}WARNING${NC}] \033[0m%b\n" "$@"
}
log::info "-------------------------------System Information----------------------------"
log::info "${GREEN}Hostname:${NC}\t\t\t"`hostname`
log::info "${GREEN}uptime:\t\t\t"`uptime | awk '{print $3,$4}' | sed 's/,//'`
log::info "${GREEN}Manufacturer:\t\t"`cat /sys/class/dmi/id/chassis_vendor`
log::info "${GREEN}Product Name:\t\t"`cat /sys/class/dmi/id/product_name`
log::info "${GREEN}Product Version:${NC}\t\t"`cat /sys/class/dmi/id/product_version`
log::info "${GREEN}Serial Number:${NC}\t\t"`cat /sys/class/dmi/id/product_serial`
lscpu | grep VMware &>/dev/null
log::info "${GREEN}Machine Type:\t\t"`if [ $? -eq 0 ]; then echo "VMware"; else echo "Physical"; fi`
log::info "${GREEN}Operating System:\t"`hostnamectl | grep "Operating System" | cut -d ' ' -f5-`
log::info "${GREEN}Version:\t\t"`cat /etc/redhat-release `
log::info "${GREEN}Kernel:\t\t\t"`uname -r`
log::info "${GREEN}Architecture:\t\t"`arch`
log::info "${GREEN}Processor Name:\t\t"`awk -F':' '/^model name/ {print $2}' /proc/cpuinfo | uniq | sed -e 's/^[ \t]*//'`
log::info "${GREEN}processor number:\t"`cat /proc/cpuinfo | grep processor | wc -l`
log::info "${GREEN}Active User:\t\t"`w | cut -d ' ' -f1 | grep -v USER | xargs -n1`
log::info "${GREEN}System Main IP:\t\t"`hostname -I`
echo ""
log::info "-------------------------------CPU/Memory Usage------------------------------"
log::info "${GREEN}Memory Usage:\t\t"`free | awk '/Mem/{printf("%.2f%"), $3/$2*100}'`
log::info "${GREEN}Swap Usage:\t\t"`free | awk '/Swap/{printf("%.2f%"), $3/$2*100}'`
log::info "${GREEN}CPU Free Space:\t\t"`top -bn 1 -i -c | grep ^% |cut -f4 -d, | awk '{print $1}'`%
log::info "${GREEN}CPU LOAD:\t\t"`top -bn 1 -i -c|grep load|awk -F','  '{print $4,$5,$6}'`%
echo ""
log::info "-------------------------------Disk Usage>20%-------------------------------"
df -Ph | sed s/%//g | awk '{ if($5 > 20) print $0;}'
echo ""
echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"

脚本执行后输出如下:

可以看到比原来的脚本输出更加整齐,更加的美观了。

OK,现在说回update-kubeadm-cert.sh 这个脚本,也就是github下载下来的脚本,下面将讲讲如何调试此脚本。




二,

脚本调试方法:

update-kubeadm-cert.sh 这个脚本内容比较多,400多行,结构是比较复杂的。

大体结构是由一个main函数和众多的子函数组成。

由于函数比较多,因此,变量定义的非常多,很多是以local的形式定义的。

此脚本需要外部参数,主要是四个外部参数:master,all ,check以及*(*代表任意参数) 也就是运行脚本的时候是 bash 脚本名称 master|all|check 这样的形式运行。

例如,带外部参数check运行此脚本,输出如下:

[root@node4 ~]# bash update-kube-cert-master/update-kubeadm-cert.sh check
CERTIFICATE                                       EXPIRES                       
/etc/kubernetes/controller-manager.config         Dec  5 13:22:20 2032 GMT      
/etc/kubernetes/scheduler.config                  Dec  5 13:22:20 2032 GMT      
/etc/kubernetes/admin.config                      Dec  5 13:22:20 2032 GMT      
/etc/kubernetes/pki/ca.crt                        Nov 12 07:26:23 2122 GMT      
/etc/kubernetes/pki/apiserver.crt                 Dec  5 13:22:20 2032 GMT      
/etc/kubernetes/pki/apiserver-kubelet-client.crt  Dec  5 13:22:20 2032 GMT      
/etc/kubernetes/pki/front-proxy-ca.crt            Nov 12 07:26:25 2122 GMT      
/etc/kubernetes/pki/front-proxy-client.crt        Dec  5 13:22:20 2032 GMT      
/etc/kubernetes/pki/etcd/ca.crt                   Nov 12 07:26:26 2122 GMT      
/etc/kubernetes/pki/etcd/server.crt               Dec  5 13:22:18 2032 GMT      
/etc/kubernetes/pki/etcd/peer.crt                 Dec  5 13:22:18 2032 GMT      
/etc/kubernetes/pki/etcd/healthcheck-client.crt   Dec  5 13:22:18 2032 GMT      
/etc/kubernetes/pki/apiserver-etcd-client.crt     Dec  5 13:22:19 2032 GMT 

那么,外部参数是*的时候(不是指定的外部参数的时候,*等于报错提示),该脚本的输出如下:

[root@node4 ~]# bash update-kube-cert-master/update-kubeadm-cert.sh ewrwerwe
[2022-12-09T12:37:35.53+0800][ERROR] unknown, unsupported cert type: ewrwerwe, supported type: "all", "master"
Documentation: https://github.com/yuyicai/update-kube-cert
  example:
    './update-kubeadm-cert.sh all' update all etcd certificates, master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-etcd-client.crt
          ├── apiserver-kubelet-client.crt
          ├── front-proxy-client.crt
          └── etcd
              ├── healthcheck-client.crt
              ├── peer.crt
              └── server.crt
    './update-kubeadm-cert.sh master' update only master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-kubelet-client.crt
          └── front-proxy-client.crt

调试思路:

1,调试脚本的时候需要暴露每一个变量,因此,脚本头设置了set -x。

2,,main函数是该脚本的主要函数,也是整个脚本的入口,因此,在main函数内增加了一个sleep 60 以作断点,脚本运行的时候会等待60秒,以方便观察每一个变量。

也就是说,不管哪个shell脚本,我们在调试的时候都需要打一个合理的断点,通常的断点是利用sleep这个内置函数。断点的位置一定要合理。

cat  update-kube-cert-master/update-kubeadm-cert.sh 
#!/usr/bin/env bash
set -x
set -o errexit
set -o pipefail
# set -o xtrace
# set output color
NC='\033[0m'
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
log::err() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${RED}ERROR${NC}] %b\n" "$@"
}
log::info() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][INFO] %b\n" "$@"
}
log::warning() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${YELLOW}WARNING${NC}] \033[0m%b\n" "$@"
}
check_file() {
  if [[ ! -r ${1} ]]; then
    log::err "can not find ${1}"
    exit 1
  fi
}
# get x509v3 subject alternative name from the old certificate
cert::get_subject_alt_name() {
  local cert=${1}.crt
  local alt_name
  check_file "${cert}"
  alt_name=$(openssl x509 -text -noout -in "${cert}" | grep -A1 'Alternative' | tail -n1 | sed 's/[[:space:]]*Address//g')
  printf "%s\n" "${alt_name}"
}
# get subject from the old certificate
cert::get_subj() {
  local cert=${1}.crt
  local subj
  check_file "${cert}"
  subj=$(openssl x509 -text -noout -in "${cert}" | grep "Subject:" | sed 's/Subject:/\//g;s/\,/\//;s/[[:space:]]//g')
  printf "%s\n" "${subj}"
}
cert::backup_file() {
  local file=${1}
  if [[ ! -e ${file}.old-$(date +%Y%m%d) ]]; then
    cp -rp "${file}" "${file}.old-$(date +%Y%m%d)"
    log::info "backup ${file} to ${file}.old-$(date +%Y%m%d)"
  else
    log::warning "does not backup, ${file}.old-$(date +%Y%m%d) already exists"
  fi
}
# check certificate expiration
cert::check_cert_expiration() {
  local cert=${1}.crt
  local cert_expires
  cert_expires=$(openssl x509 -text -noout -in "${cert}" | awk -F ": " '/Not After/{print$2}')
  printf "%s\n" "${cert_expires}"
}
# check kubeconfig expiration
cert::check_kubeconfig_expiration() {
  local config=${1}.conf
  local cert
  local cert_expires
  cert=$(grep "client-certificate-data" "${config}" | awk '{print$2}' | base64 -d)
  cert_expires=$(openssl x509 -text -noout -in <(printf "%s" "${cert}") | awk -F ": " '/Not After/{print$2}')
  printf "%s\n" "${cert_expires}"
}
# check etcd certificates expiration
cert::check_etcd_certs_expiration() {
  local cert
  local certs
  certs=(
    "${ETCD_CERT_CA}"
    "${ETCD_CERT_SERVER}"
    "${ETCD_CERT_PEER}"
    "${ETCD_CERT_HEALTHCHECK_CLIENT}"
    "${ETCD_CERT_APISERVER_ETCD_CLIENT}"
  )
  for cert in "${certs[@]}"; do
    if [[ ! -r ${cert} ]]; then
      printf "%-50s%-30s\n" "${cert}.crt" "$(cert::check_cert_expiration "${cert}")"
    fi
  done
}
# check master certificates expiration
cert::check_master_certs_expiration() {
  local certs
  local kubeconfs
  local cert
  local conf
  certs=(
    "${CERT_CA}"
    "${CERT_APISERVER}"
    "${CERT_APISERVER_KUBELET_CLIENT}"
    "${FRONT_PROXY_CA}"
    "${FRONT_PROXY_CLIENT}"
  )
  kubeconfs=(
    "${CONF_CONTROLLER_MANAGER}"
    "${CONF_SCHEDULER}"
    "${CONF_ADMIN}"
  )
  printf "%-50s%-30s\n" "CERTIFICATE" "EXPIRES"
  for conf in "${kubeconfs[@]}"; do
    if [[ ! -r ${conf} ]]; then
      printf "%-50s%-30s\n" "${conf}.config" "$(cert::check_kubeconfig_expiration "${conf}")"
    fi
  done
  for cert in "${certs[@]}"; do
    if [[ ! -r ${cert} ]]; then
      printf "%-50s%-30s\n" "${cert}.crt" "$(cert::check_cert_expiration "${cert}")"
    fi
  done
}
# check all certificates expiration
cert::check_all_expiration() {
  cert::check_master_certs_expiration
  cert::check_etcd_certs_expiration
}
# generate certificate whit client, server or peer
# Args:
#   $1 (the name of certificate)
#   $2 (the type of certificate, must be one of client, server, peer)
#   $3 (the subject of certificates)
#   $4 (the validity of certificates) (days)
#   $5 (the name of ca)
#   $6 (the x509v3 subject alternative name of certificate when the type of certificate is server or peer)
cert::gen_cert() {
  local cert_name=${1}
  local cert_type=${2}
  local subj=${3}
  local cert_days=${4}
  local ca_name=${5}
  local alt_name=${6}
  local ca_cert=${ca_name}.crt
  local ca_key=${ca_name}.key
  local cert=${cert_name}.crt
  local key=${cert_name}.key
  local csr=${cert_name}.csr
  local common_csr_conf='distinguished_name = dn\n[dn]\n[v3_ext]\nkeyUsage = critical, digitalSignature, keyEncipherment\n'
  for file in "${ca_cert}" "${ca_key}" "${cert}" "${key}"; do
    check_file "${file}"
  done
  case "${cert_type}" in
  client)
    csr_conf=$(printf "%bextendedKeyUsage = clientAuth\n" "${common_csr_conf}")
    ;;
  server)
    csr_conf=$(printf "%bextendedKeyUsage = serverAuth\nsubjectAltName = %b\n" "${common_csr_conf}" "${alt_name}")
    ;;
  peer)
    csr_conf=$(printf "%bextendedKeyUsage = serverAuth, clientAuth\nsubjectAltName = %b\n" "${common_csr_conf}" "${alt_name}")
    ;;
  *)
    log::err "unknow, unsupported certs type: ${YELLOW}${cert_type}${NC}, supported type: client, server, peer"
    exit 1
    ;;
  esac
  # gen csr
  openssl req -new -key "${key}" -subj "${subj}" -reqexts v3_ext \
    -config <(printf "%b" "${csr_conf}") \
    -out "${csr}" >/dev/null 2>&1
  # gen cert
  openssl x509 -in "${csr}" -req -CA "${ca_cert}" -CAkey "${ca_key}" -CAcreateserial -extensions v3_ext \
    -extfile <(printf "%b" "${csr_conf}") \
    -days "${cert_days}" -out "${cert}" >/dev/null 2>&1
  rm -f "${csr}"
}
cert::update_kubeconf() {
  local cert_name=${1}
  local kubeconf_file=${cert_name}.conf
  local cert=${cert_name}.crt
  local key=${cert_name}.key
  local subj
  local cert_base64
  check_file "${kubeconf_file}"
  # get the key from the old kubeconf
  grep "client-key-data" "${kubeconf_file}" | awk '{print$2}' | base64 -d >"${key}"
  # get the old certificate from the old kubeconf
  grep "client-certificate-data" "${kubeconf_file}" | awk '{print$2}' | base64 -d >"${cert}"
  # get subject from the old certificate
  subj=$(cert::get_subj "${cert_name}")
  cert::gen_cert "${cert_name}" "client" "${subj}" "${CERT_DAYS}" "${CERT_CA}"
  # get certificate base64 code
  cert_base64=$(base64 -w 0 "${cert}")
  # set certificate base64 code to kubeconf
  sed -i 's/client-certificate-data:.*/client-certificate-data: '"${cert_base64}"'/g' "${kubeconf_file}"
  rm -f "${cert}"
  rm -f "${key}"
}
cert::update_etcd_cert() {
  local subj
  local subject_alt_name
  local cert
  # generate etcd server,peer certificate
  # /etc/kubernetes/pki/etcd/server
  # /etc/kubernetes/pki/etcd/peer
  for cert in ${ETCD_CERT_SERVER} ${ETCD_CERT_PEER}; do
    subj=$(cert::get_subj "${cert}")
    subject_alt_name=$(cert::get_subject_alt_name "${cert}")
    cert::gen_cert "${cert}" "peer" "${subj}" "${CERT_DAYS}" "${ETCD_CERT_CA}" "${subject_alt_name}"
    log::info "${GREEN}updated ${BLUE}${cert}.conf${NC}"
  done
  # generate etcd healthcheck-client,apiserver-etcd-client certificate
  # /etc/kubernetes/pki/etcd/healthcheck-client
  # /etc/kubernetes/pki/apiserver-etcd-client
  for cert in ${ETCD_CERT_HEALTHCHECK_CLIENT} ${ETCD_CERT_APISERVER_ETCD_CLIENT}; do
    subj=$(cert::get_subj "${cert}")
    cert::gen_cert "${cert}" "client" "${subj}" "${CERT_DAYS}" "${ETCD_CERT_CA}"
    log::info "${GREEN}updated ${BLUE}${cert}.conf${NC}"
  done
  # restart etcd
  docker ps | awk '/k8s_etcd/{print$1}' | xargs -r -I '{}' docker restart {} >/dev/null 2>&1 || true
  log::info "restarted etcd"
}
cert::update_master_cert() {
  local subj
  local subject_alt_name
  local conf
  # generate apiserver server certificate
  # /etc/kubernetes/pki/apiserver
  subj=$(cert::get_subj "${CERT_APISERVER}")
  subject_alt_name=$(cert::get_subject_alt_name "${CERT_APISERVER}")
  cert::gen_cert "${CERT_APISERVER}" "server" "${subj}" "${CERT_DAYS}" "${CERT_CA}" "${subject_alt_name}"
  log::info "${GREEN}updated ${BLUE}${CERT_APISERVER}.crt${NC}"
  # generate apiserver-kubelet-client certificate
  # /etc/kubernetes/pki/apiserver-kubelet-client
  subj=$(cert::get_subj "${CERT_APISERVER_KUBELET_CLIENT}")
  cert::gen_cert "${CERT_APISERVER_KUBELET_CLIENT}" "client" "${subj}" "${CERT_DAYS}" "${CERT_CA}"
  log::info "${GREEN}updated ${BLUE}${CERT_APISERVER_KUBELET_CLIENT}.crt${NC}"
  # generate kubeconf for controller-manager,scheduler and kubelet
  # /etc/kubernetes/controller-manager,scheduler,admin,kubelet.conf
  for conf in ${CONF_CONTROLLER_MANAGER} ${CONF_SCHEDULER} ${CONF_ADMIN} ${CONF_KUBELET}; do
    if [[ ${conf##*/} == "kubelet" ]]; then
      # https://github.com/kubernetes/kubeadm/issues/1753
      set +e
      grep kubelet-client-current.pem /etc/kubernetes/kubelet.conf >/dev/null 2>&1
      kubelet_cert_auto_update=$?
      set -e
      if [[ "$kubelet_cert_auto_update" == "0" ]]; then
        log::info "does not need to update kubelet.conf"
        continue
      fi
    fi
    # update kubeconf
    cert::update_kubeconf "${conf}"
    log::info "${GREEN}updated ${BLUE}${conf}.conf${NC}"
    # copy admin.conf to ${HOME}/.kube/config
    if [[ ${conf##*/} == "admin" ]]; then
      mkdir -p "${HOME}/.kube"
      local config=${HOME}/.kube/config
      local config_backup
      config_backup=${HOME}/.kube/config.old-$(date +%Y%m%d)
      if [[ -f ${config} ]] && [[ ! -f ${config_backup} ]]; then
        cp -fp "${config}" "${config_backup}"
        log::info "backup ${config} to ${config_backup}"
      fi
      cp -fp "${conf}.conf" "${HOME}/.kube/config"
      log::info "copy the admin.conf to ${HOME}/.kube/config"
    fi
  done
  # generate front-proxy-client certificate
  # /etc/kubernetes/pki/front-proxy-client
  subj=$(cert::get_subj "${FRONT_PROXY_CLIENT}")
  cert::gen_cert "${FRONT_PROXY_CLIENT}" "client" "${subj}" "${CERT_DAYS}" "${FRONT_PROXY_CA}"
  log::info "${GREEN}updated ${BLUE}${FRONT_PROXY_CLIENT}.crt${NC}"
  # restart apiserver, controller-manager, scheduler and kubelet
  for item in "apiserver" "controller-manager" "scheduler"; do
    docker ps | awk '/k8s_kube-'${item}'/{print$1}' | xargs -r -I '{}' docker restart {} >/dev/null 2>&1 || true
    log::info "restarted ${item}"
  done
  systemctl restart kubelet || true
  log::info "restarted kubelet"
}
main() {
  local node_type=$1
  CERT_DAYS=3650
  KUBE_PATH=/etc/kubernetes
  PKI_PATH=${KUBE_PATH}/pki
  # master certificates path
  # apiserver
  CERT_CA=${PKI_PATH}/ca
  CERT_APISERVER=${PKI_PATH}/apiserver
  CERT_APISERVER_KUBELET_CLIENT=${PKI_PATH}/apiserver-kubelet-client
  CONF_CONTROLLER_MANAGER=${KUBE_PATH}/controller-manager
  CONF_SCHEDULER=${KUBE_PATH}/scheduler
  CONF_ADMIN=${KUBE_PATH}/admin
  CONF_KUBELET=${KUBE_PATH}/kubelet
  # front-proxy
  FRONT_PROXY_CA=${PKI_PATH}/front-proxy-ca
  FRONT_PROXY_CLIENT=${PKI_PATH}/front-proxy-client
  # etcd certificates path
  ETCD_CERT_CA=${PKI_PATH}/etcd/ca
  ETCD_CERT_SERVER=${PKI_PATH}/etcd/server
  ETCD_CERT_PEER=${PKI_PATH}/etcd/peer
  ETCD_CERT_HEALTHCHECK_CLIENT=${PKI_PATH}/etcd/healthcheck-client
  ETCD_CERT_APISERVER_ETCD_CLIENT=${PKI_PATH}/apiserver-etcd-client
  case ${node_type} in
  # etcd)
  # # update etcd certificates
  #   cert::update_etcd_cert
  # ;;
  master)
    # check certificates expiration
    cert::check_master_certs_expiration
    # backup $KUBE_PATH to $KUBE_PATH.old-$(date +%Y%m%d)
    cert::backup_file "${KUBE_PATH}"
    # update master certificates and kubeconf
    log::info "${GREEN}updating...${NC}"
    cert::update_master_cert
    log::info "${GREEN}done!!!${NC}"
    # check certificates expiration after certificates updated
    cert::check_master_certs_expiration
    ;;
  all)
    # check certificates expiration
    cert::check_all_expiration
sleep 60
    # backup $KUBE_PATH to $KUBE_PATH.old-$(date +%Y%m%d)
    cert::backup_file "${KUBE_PATH}"
    # update etcd certificates
    log::info "${GREEN}updating...${NC}"
    cert::update_etcd_cert
    # update master certificates and kubeconf
    cert::update_master_cert
    log::info "${GREEN}done!!!${NC}"
    # check certificates expiration after certificates updated
    cert::check_all_expiration
    ;;
  check)
    # check certificates expiration
    cert::check_all_expiration
    ;;
  *)
    log::err "unknown, unsupported cert type: ${node_type}, supported type: \"all\", \"master\""
    printf "Documentation: https://github.com/yuyicai/update-kube-cert
  example:
    '\033[32m./update-kubeadm-cert.sh all\033[0m' update all etcd certificates, master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-etcd-client.crt
          ├── apiserver-kubelet-client.crt
          ├── front-proxy-client.crt
          └── etcd
              ├── healthcheck-client.crt
              ├── peer.crt
              └── server.crt
    '\033[32m./update-kubeadm-cert.sh master\033[0m' update only master certificates and kubeconf
      /etc/kubernetes
      ├── admin.conf
      ├── controller-manager.conf
      ├── scheduler.conf
      ├── kubelet.conf
      └── pki
          ├── apiserver.crt
          ├── apiserver-kubelet-client.crt
          └── front-proxy-client.crt
"
    exit 1
    ;;
  esac
}
main "$@"

这里使用的参数是all,因此,在all参数下的第一个函数打断点sleep 60,如果是使用master参数,那么,应该在master下的第一个函数打断点。

该脚本的调试命令是:

bash  update-kube-cert-master/update-kubeadm-cert.sh  all

输出的日志如下:

可以看到,我们使用的参数是all,那么,如果想让该脚本更新证书不是10年而是100年,自然需要将变量CERT_DAYS=3650修改为CERT_DAYS=36500了。

[root@node4 ~]# bash  update-kube-cert-master/update-kubeadm-cert.sh  all 
+ set -o errexit
+ set -o pipefail
+ NC='\033[0m'
+ RED='\033[31m'
+ GREEN='\033[32m'
+ YELLOW='\033[33m'
+ BLUE='\033[34m'
+ main all
+ local node_type=all
+ CERT_DAYS=3650
+ KUBE_PATH=/etc/kubernetes
+ PKI_PATH=/etc/kubernetes/pki
+ CERT_CA=/etc/kubernetes/pki/ca
+ CERT_APISERVER=/etc/kubernetes/pki/apiserver
+ CERT_APISERVER_KUBELET_CLIENT=/etc/kubernetes/pki/apiserver-kubelet-client
+ CONF_CONTROLLER_MANAGER=/etc/kubernetes/controller-manager
+ CONF_SCHEDULER=/etc/kubernetes/scheduler
+ CONF_ADMIN=/etc/kubernetes/admin
+ CONF_KUBELET=/etc/kubernetes/kubelet
+ FRONT_PROXY_CA=/etc/kubernetes/pki/front-proxy-ca
+ FRONT_PROXY_CLIENT=/etc/kubernetes/pki/front-proxy-client
+ ETCD_CERT_CA=/etc/kubernetes/pki/etcd/ca
+ ETCD_CERT_SERVER=/etc/kubernetes/pki/etcd/server
+ ETCD_CERT_PEER=/etc/kubernetes/pki/etcd/peer
+ ETCD_CERT_HEALTHCHECK_CLIENT=/etc/kubernetes/pki/etcd/healthcheck-client
+ ETCD_CERT_APISERVER_ETCD_CLIENT=/etc/kubernetes/pki/apiserver-etcd-client
+ case ${node_type} in
+ cert::check_all_expiration
+ cert::check_master_certs_expiration
+ local certs
+ local kubeconfs
+ local cert
+ local conf
+ certs=("${CERT_CA}" "${CERT_APISERVER}" "${CERT_APISERVER_KUBELET_CLIENT}" "${FRONT_PROXY_CA}" "${FRONT_PROXY_CLIENT}")
+ kubeconfs=("${CONF_CONTROLLER_MANAGER}" "${CONF_SCHEDULER}" "${CONF_ADMIN}")
+ printf '%-50s%-30s\n' CERTIFICATE EXPIRES
CERTIFICATE                                       EXPIRES                       
+ for conf in '"${kubeconfs[@]}"'
+ [[ ! -r /etc/kubernetes/controller-manager ]]
++ cert::check_kubeconfig_expiration /etc/kubernetes/controller-manager
++ local config=/etc/kubernetes/controller-manager.conf
++ local cert
++ local cert_expires
+++ grep client-certificate-data /etc/kubernetes/controller-manager.conf
+++ base64 -d
+++ awk '{print$2}'
++ cert='-----BEGIN CERTIFICATE-----
MIIC6DCCAdCgAwIBAgIJANAYEYivHZr6MA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMTCmt1YmVybmV0ZXMwHhcNMjIxMjA4MTMyMjIwWhcNMzIxMjA1MTMyMjIwWjAp
MScwJQYDVQQDDB5zeXN0ZW06a3ViZS1jb250cm9sbGVyLW1hbmFnZXIwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbCNdZWfw9BjCkkCDt1DvZUwp9Xn41
9K+Ijy2kelms5KW+qRF9mTChEtjIJG1jO+ul1cx2XBgi+x9G3R2ErPe3rX9tt0wu
3MK7BZC8KRzlAK8dRSkCL+28PsHpr+mcQxYNNZnpEHyyCahaVy2IfGtb4xBCp2CS
AaEUIXJkI4pjLIKjv11NRi3oBJbUh8CyUms/5RFhXxqUfsX7u85+NcXku1h429Wz
cRSF9PgSHuPoBiiJdtrHbQyErd0mLJEZxgLz9MEc2YiNSL6ORoV8Kfxba1Z05c1W
0waNxCrHA9uqO3NHMM9dagJhS3A5vyczvRgm6dVMrvDJFvvKaf9StZVNAgMBAAGj
JzAlMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG
9w0BAQsFAAOCAQEAOsz8bmnrUdpOAigDZWI8gPwQcqmP82RxLLUXakhwo6v31AEk
tQETDb9ypXo99/6KHXLKc0g0jRTnOPywqIqOvDRXbzsWHQOamvcyP0xnVY4VSwVg
3J+yR04sgS6XjN42AymR2IUFzZDY5g7bJYH0+LHFTqlkiI1vt7vdoWrpKU9XUmxP
kv5lLVI2DgvMosgcvib6c5JakpzZgw4jnhYI2bulAReYMdHSMBS/ZRTNKuggWXQj
IejnirR+JUeZYKkVJqAGXUGiMksNgE4P79N+mcAtvFhH8oolGCAXATH7tRJ74odd
Q2azcimFOuifoDYveer/vbGH8pjsKveesORTVw==
-----END CERTIFICATE-----'
+++ openssl x509 -text -noout -in /dev/fd/63
++++ printf %s '-----BEGIN CERTIFICATE-----
MIIC6DCCAdCgAwIBAgIJANAYEYivHZr6MA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMTCmt1YmVybmV0ZXMwHhcNMjIxMjA4MTMyMjIwWhcNMzIxMjA1MTMyMjIwWjAp
MScwJQYDVQQDDB5zeXN0ZW06a3ViZS1jb250cm9sbGVyLW1hbmFnZXIwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbCNdZWfw9BjCkkCDt1DvZUwp9Xn41
9K+Ijy2kelms5KW+qRF9mTChEtjIJG1jO+ul1cx2XBgi+x9G3R2ErPe3rX9tt0wu
3MK7BZC8KRzlAK8dRSkCL+28PsHpr+mcQxYNNZnpEHyyCahaVy2IfGtb4xBCp2CS
AaEUIXJkI4pjLIKjv11NRi3oBJbUh8CyUms/5RFhXxqUfsX7u85+NcXku1h429Wz
cRSF9PgSHuPoBiiJdtrHbQyErd0mLJEZxgLz9MEc2YiNSL6ORoV8Kfxba1Z05c1W
0waNxCrHA9uqO3NHMM9dagJhS3A5vyczvRgm6dVMrvDJFvvKaf9StZVNAgMBAAGj
JzAlMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG
9w0BAQsFAAOCAQEAOsz8bmnrUdpOAigDZWI8gPwQcqmP82RxLLUXakhwo6v31AEk
tQETDb9ypXo99/6KHXLKc0g0jRTnOPywqIqOvDRXbzsWHQOamvcyP0xnVY4VSwVg
3J+yR04sgS6XjN42AymR2IUFzZDY5g7bJYH0+LHFTqlkiI1vt7vdoWrpKU9XUmxP
kv5lLVI2DgvMosgcvib6c5JakpzZgw4jnhYI2bulAReYMdHSMBS/ZRTNKuggWXQj
IejnirR+JUeZYKkVJqAGXUGiMksNgE4P79N+mcAtvFhH8oolGCAXATH7tRJ74odd
Q2azcimFOuifoDYveer/vbGH8pjsKveesORTVw==
-----END CERTIFICATE-----'
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Dec  5 13:22:20 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:20 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/controller-manager.config 'Dec  5 13:22:20 2032 GMT'
/etc/kubernetes/controller-manager.config         Dec  5 13:22:20 2032 GMT      
+ for conf in '"${kubeconfs[@]}"'
+ [[ ! -r /etc/kubernetes/scheduler ]]
++ cert::check_kubeconfig_expiration /etc/kubernetes/scheduler
++ local config=/etc/kubernetes/scheduler.conf
++ local cert
++ local cert_expires
+++ grep client-certificate-data /etc/kubernetes/scheduler.conf
+++ base64 -d
+++ awk '{print$2}'
++ cert='-----BEGIN CERTIFICATE-----
MIIC3zCCAcegAwIBAgIJANAYEYivHZr7MA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMTCmt1YmVybmV0ZXMwHhcNMjIxMjA4MTMyMjIwWhcNMzIxMjA1MTMyMjIwWjAg
MR4wHAYDVQQDDBVzeXN0ZW06a3ViZS1zY2hlZHVsZXIwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCuQkja6VTRgUKRXb20HmMw+kABEGlr5z4zZDxYRRcu
FKhEDBLr3neIQLd4u+dehhW70QelAEK+1Z9tiu3dWxmnI5Z0W2dkurtdtyN7QMux
aknsmZKaeMlgdMR0e01AIuESlSOWsBQqnPtiqpbuQgSe5G0YwfXxQ/Jj22JuUB9t
P7sAEpFEBl2xDWlDWeNUajNx65R6YfjolSGwHp19WHSuA3Ed+DLpQAFTEaIMAOjf
YFNcXhJDEHdn+LYjs2oaQTzurGu7EhHoU5Y7ka6wos7PLRyrC8xDskbnh8pvQKpP
Z2oFk71TxLH5nMy3ENnimSEIPJM021Zm+gSN8JR7dlWbAgMBAAGjJzAlMA4GA1Ud
DwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOC
AQEAZx1FiXfJgac58S3gULr1ICrIsl0Cn6vNJ2XKH8B3ZGucaFENEE8tq0auHcEn
lcN/bbPwO4TPuXNTBSE9M4F267I0/ybuFg54tnW+4jQUa2rRobo5GWVKvbQJk3cb
OLX2vbT5S2ctvqcYsHqEHTPivPug7APcfkGnWzp64p/7FiFhMrcX9R8+MhJDT4/G
CU1BEL2CypeVpgbwaZe84xoLxdBqHJ+PxxN7pfChWwPfP8ZqVmSv6ugURTJr5vRS
yejsgc9T19TaYbLBv8skR/EStHo6O+1gFLSC1h5hks0TYGF8k5IBlFJlNGoFlJgg
/rX0FKv0EHsUeaonDDDZFxdXew==
-----END CERTIFICATE-----'
+++ awk -F ': ' '/Not After/{print$2}'
+++ openssl x509 -text -noout -in /dev/fd/63
++++ printf %s '-----BEGIN CERTIFICATE-----
MIIC3zCCAcegAwIBAgIJANAYEYivHZr7MA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMTCmt1YmVybmV0ZXMwHhcNMjIxMjA4MTMyMjIwWhcNMzIxMjA1MTMyMjIwWjAg
MR4wHAYDVQQDDBVzeXN0ZW06a3ViZS1zY2hlZHVsZXIwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCuQkja6VTRgUKRXb20HmMw+kABEGlr5z4zZDxYRRcu
FKhEDBLr3neIQLd4u+dehhW70QelAEK+1Z9tiu3dWxmnI5Z0W2dkurtdtyN7QMux
aknsmZKaeMlgdMR0e01AIuESlSOWsBQqnPtiqpbuQgSe5G0YwfXxQ/Jj22JuUB9t
P7sAEpFEBl2xDWlDWeNUajNx65R6YfjolSGwHp19WHSuA3Ed+DLpQAFTEaIMAOjf
YFNcXhJDEHdn+LYjs2oaQTzurGu7EhHoU5Y7ka6wos7PLRyrC8xDskbnh8pvQKpP
Z2oFk71TxLH5nMy3ENnimSEIPJM021Zm+gSN8JR7dlWbAgMBAAGjJzAlMA4GA1Ud
DwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOC
AQEAZx1FiXfJgac58S3gULr1ICrIsl0Cn6vNJ2XKH8B3ZGucaFENEE8tq0auHcEn
lcN/bbPwO4TPuXNTBSE9M4F267I0/ybuFg54tnW+4jQUa2rRobo5GWVKvbQJk3cb
OLX2vbT5S2ctvqcYsHqEHTPivPug7APcfkGnWzp64p/7FiFhMrcX9R8+MhJDT4/G
CU1BEL2CypeVpgbwaZe84xoLxdBqHJ+PxxN7pfChWwPfP8ZqVmSv6ugURTJr5vRS
yejsgc9T19TaYbLBv8skR/EStHo6O+1gFLSC1h5hks0TYGF8k5IBlFJlNGoFlJgg
/rX0FKv0EHsUeaonDDDZFxdXew==
-----END CERTIFICATE-----'
++ cert_expires='Dec  5 13:22:20 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:20 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/scheduler.config 'Dec  5 13:22:20 2032 GMT'
/etc/kubernetes/scheduler.config                  Dec  5 13:22:20 2032 GMT      
+ for conf in '"${kubeconfs[@]}"'
+ [[ ! -r /etc/kubernetes/admin ]]
++ cert::check_kubeconfig_expiration /etc/kubernetes/admin
++ local config=/etc/kubernetes/admin.conf
++ local cert
++ local cert_expires
+++ grep client-certificate-data /etc/kubernetes/admin.conf
+++ base64 -d
+++ awk '{print$2}'
++ cert='-----BEGIN CERTIFICATE-----
MIIC8zCCAdugAwIBAgIJANAYEYivHZr8MA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMTCmt1YmVybmV0ZXMwHhcNMjIxMjA4MTMyMjIwWhcNMzIxMjA1MTMyMjIwWjA0
MRcwFQYDVQQKDA5zeXN0ZW06bWFzdGVyczEZMBcGA1UEAwwQa3ViZXJuZXRlcy1h
ZG1pbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVJbVqTIzMU7DLL
CoOV6IW3vVjYIg8EnytEHRH7yJ1SnTxdq9FEwNKjW+bZk5vYygEswBkjgHQlGNdu
BJIma3lPTNCifDykV/kb1kV8o5eU5b6/A8nRr/tpIeUxTCK2T9v6Ep91KgflNzFk
AM+VNp3XWwVV4pBBeX6IXBBCmQdjyJ9qzeOZZGyP5aL/Q4JCw6v1FlHb+9Ja2fTB
NCSH3j57618KGXqfcAmUex+Si1gfou7OuqmUDjYbSGDGMFucQkEdkx5bK5QQRtRw
QfdEq9bB06iYdJng2uvq6GeW+0cx8ef/56AY2CCJjAIzpOtb2yOfIt6PkVYiLvyz
0a3wZ8sCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUF
BwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCRD0+WujKggavu8tgzWlR93Wh2zoDz/Rkd
gFsErhjWuzEwUFjNNhIBlPzOubjoVvzG0KQEImIsSBTbmV5hShOwocqYAA1uRFW5
t11dbeTF5HqZbtmbhJ0y26SdTFIRD0xEydq91P6lB5TqEbis/+Il7y/hGvZKtRcB
Gf87fk5zdQlxAg5nx2i+wj73yYcQFlgEu+2RFo8XejEbqbkrQ470DA5W+TNpPbEH
rMmGsh6EeFP5hnntxkvAf7kBgirKbXfTpPveKP7yT/aiUB1KCuV4ZCSRWrA9sBvJ
hwbZFI2LriP6nlJh0IIiyoygS/G3IFQ1ner0jNIsYJNY4LmZKQD5
-----END CERTIFICATE-----'
+++ awk -F ': ' '/Not After/{print$2}'
+++ openssl x509 -text -noout -in /dev/fd/63
++++ printf %s '-----BEGIN CERTIFICATE-----
MIIC8zCCAdugAwIBAgIJANAYEYivHZr8MA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
BAMTCmt1YmVybmV0ZXMwHhcNMjIxMjA4MTMyMjIwWhcNMzIxMjA1MTMyMjIwWjA0
MRcwFQYDVQQKDA5zeXN0ZW06bWFzdGVyczEZMBcGA1UEAwwQa3ViZXJuZXRlcy1h
ZG1pbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVJbVqTIzMU7DLL
CoOV6IW3vVjYIg8EnytEHRH7yJ1SnTxdq9FEwNKjW+bZk5vYygEswBkjgHQlGNdu
BJIma3lPTNCifDykV/kb1kV8o5eU5b6/A8nRr/tpIeUxTCK2T9v6Ep91KgflNzFk
AM+VNp3XWwVV4pBBeX6IXBBCmQdjyJ9qzeOZZGyP5aL/Q4JCw6v1FlHb+9Ja2fTB
NCSH3j57618KGXqfcAmUex+Si1gfou7OuqmUDjYbSGDGMFucQkEdkx5bK5QQRtRw
QfdEq9bB06iYdJng2uvq6GeW+0cx8ef/56AY2CCJjAIzpOtb2yOfIt6PkVYiLvyz
0a3wZ8sCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUF
BwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCRD0+WujKggavu8tgzWlR93Wh2zoDz/Rkd
gFsErhjWuzEwUFjNNhIBlPzOubjoVvzG0KQEImIsSBTbmV5hShOwocqYAA1uRFW5
t11dbeTF5HqZbtmbhJ0y26SdTFIRD0xEydq91P6lB5TqEbis/+Il7y/hGvZKtRcB
Gf87fk5zdQlxAg5nx2i+wj73yYcQFlgEu+2RFo8XejEbqbkrQ470DA5W+TNpPbEH
rMmGsh6EeFP5hnntxkvAf7kBgirKbXfTpPveKP7yT/aiUB1KCuV4ZCSRWrA9sBvJ
hwbZFI2LriP6nlJh0IIiyoygS/G3IFQ1ner0jNIsYJNY4LmZKQD5
-----END CERTIFICATE-----'
++ cert_expires='Dec  5 13:22:20 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:20 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/admin.config 'Dec  5 13:22:20 2032 GMT'
/etc/kubernetes/admin.config                      Dec  5 13:22:20 2032 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/ca ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/ca
++ local cert=/etc/kubernetes/pki/ca.crt
++ local cert_expires
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/ca.crt
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Nov 12 07:26:23 2122 GMT'
++ printf '%s\n' 'Nov 12 07:26:23 2122 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/ca.crt 'Nov 12 07:26:23 2122 GMT'
/etc/kubernetes/pki/ca.crt                        Nov 12 07:26:23 2122 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/apiserver ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/apiserver
++ local cert=/etc/kubernetes/pki/apiserver.crt
++ local cert_expires
+++ awk -F ': ' '/Not After/{print$2}'
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/apiserver.crt
++ cert_expires='Dec  5 13:22:20 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:20 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/apiserver.crt 'Dec  5 13:22:20 2032 GMT'
/etc/kubernetes/pki/apiserver.crt                 Dec  5 13:22:20 2032 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/apiserver-kubelet-client ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/apiserver-kubelet-client
++ local cert=/etc/kubernetes/pki/apiserver-kubelet-client.crt
++ local cert_expires
+++ awk -F ': ' '/Not After/{print$2}'
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/apiserver-kubelet-client.crt
++ cert_expires='Dec  5 13:22:20 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:20 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/apiserver-kubelet-client.crt 'Dec  5 13:22:20 2032 GMT'
/etc/kubernetes/pki/apiserver-kubelet-client.crt  Dec  5 13:22:20 2032 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/front-proxy-ca ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/front-proxy-ca
++ local cert=/etc/kubernetes/pki/front-proxy-ca.crt
++ local cert_expires
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/front-proxy-ca.crt
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Nov 12 07:26:25 2122 GMT'
++ printf '%s\n' 'Nov 12 07:26:25 2122 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/front-proxy-ca.crt 'Nov 12 07:26:25 2122 GMT'
/etc/kubernetes/pki/front-proxy-ca.crt            Nov 12 07:26:25 2122 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/front-proxy-client ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/front-proxy-client
++ local cert=/etc/kubernetes/pki/front-proxy-client.crt
++ local cert_expires
+++ awk -F ': ' '/Not After/{print$2}'
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/front-proxy-client.crt
++ cert_expires='Dec  5 13:22:20 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:20 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/front-proxy-client.crt 'Dec  5 13:22:20 2032 GMT'
/etc/kubernetes/pki/front-proxy-client.crt        Dec  5 13:22:20 2032 GMT      
+ cert::check_etcd_certs_expiration
+ local cert
+ local certs
+ certs=("${ETCD_CERT_CA}" "${ETCD_CERT_SERVER}" "${ETCD_CERT_PEER}" "${ETCD_CERT_HEALTHCHECK_CLIENT}" "${ETCD_CERT_APISERVER_ETCD_CLIENT}")
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/etcd/ca ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/etcd/ca
++ local cert=/etc/kubernetes/pki/etcd/ca.crt
++ local cert_expires
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/etcd/ca.crt
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Nov 12 07:26:26 2122 GMT'
++ printf '%s\n' 'Nov 12 07:26:26 2122 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/etcd/ca.crt 'Nov 12 07:26:26 2122 GMT'
/etc/kubernetes/pki/etcd/ca.crt                   Nov 12 07:26:26 2122 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/etcd/server ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/etcd/server
++ local cert=/etc/kubernetes/pki/etcd/server.crt
++ local cert_expires
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/etcd/server.crt
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Dec  5 13:22:18 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:18 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/etcd/server.crt 'Dec  5 13:22:18 2032 GMT'
/etc/kubernetes/pki/etcd/server.crt               Dec  5 13:22:18 2032 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/etcd/peer ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/etcd/peer
++ local cert=/etc/kubernetes/pki/etcd/peer.crt
++ local cert_expires
+++ awk -F ': ' '/Not After/{print$2}'
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/etcd/peer.crt
++ cert_expires='Dec  5 13:22:18 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:18 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/etcd/peer.crt 'Dec  5 13:22:18 2032 GMT'
/etc/kubernetes/pki/etcd/peer.crt                 Dec  5 13:22:18 2032 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/etcd/healthcheck-client ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/etcd/healthcheck-client
++ local cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt
++ local cert_expires
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/etcd/healthcheck-client.crt
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Dec  5 13:22:18 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:18 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/etcd/healthcheck-client.crt 'Dec  5 13:22:18 2032 GMT'
/etc/kubernetes/pki/etcd/healthcheck-client.crt   Dec  5 13:22:18 2032 GMT      
+ for cert in '"${certs[@]}"'
+ [[ ! -r /etc/kubernetes/pki/apiserver-etcd-client ]]
++ cert::check_cert_expiration /etc/kubernetes/pki/apiserver-etcd-client
++ local cert=/etc/kubernetes/pki/apiserver-etcd-client.crt
++ local cert_expires
+++ openssl x509 -text -noout -in /etc/kubernetes/pki/apiserver-etcd-client.crt
+++ awk -F ': ' '/Not After/{print$2}'
++ cert_expires='Dec  5 13:22:19 2032 GMT'
++ printf '%s\n' 'Dec  5 13:22:19 2032 GMT'
+ printf '%-50s%-30s\n' /etc/kubernetes/pki/apiserver-etcd-client.crt 'Dec  5 13:22:19 2032 GMT'
/etc/kubernetes/pki/apiserver-etcd-client.crt     Dec  5 13:22:19 2032 GMT      
+ sleep 60

观察以上的输出,我们可以发现另外两个关键的变量:

  KUBE_PATH=/etc/kubernetes
  PKI_PATH=${KUBE_PATH}/pki

因此,我们即使不执行此脚本,也能知道该脚本更新以及备份kubernetes集群的范围只能是kubeadm方式部署的集群。

那么,这个脚本的意义在于可以把它里面的备份功能和重启服务功能独立出来。

这里先说一下脚本的重启服务功能,此功能是通过docker 重启容器的方式来变相的实现重启服务,因为我们都知道,kubeadm的关键服务都是静态pod的形式部署的嘛,自然是pod的容器重启了,服务就等于重启了。

这个服务重启的功能是证书更新的基础,如果证书更新完毕了,服务还没有重启,那么自然的,证书等于没有更新。

kubernetes集群核心服务重启脚本:

OK,服务重启的功能代码如下(这个是一个独立的脚本,当然了,适用于所有的kubeadm部署的集群,执行此脚本将会重启kubernetes集群的三个核心服务):

#!/bin/bash
log::info() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][INFO] %b\n" "$@"
}
  for item in "apiserver" "controller-manager" "scheduler"; do
    docker ps | awk '/k8s_kube-'${item}'/{print$1}' | xargs -r -I '{}' docker restart {} >/dev/null 2>&1 || true
    log::info "restarted ${item}"
  done

执行此脚本后的输出如下;

[root@node4 ~]# bash 3333.sh 
[2022-12-09T01:18:11.97+0800][INFO] restarted apiserver
[2022-12-09T01:18:12.10+0800][INFO] restarted controller-manager
[2022-12-09T01:18:12.20+0800][INFO] restarted scheduler

如何证明这三个服务重启了呢?这个比较简单,我们观察pod的状态即可,容器每重启一次,restarts都会增加1:

[root@node4 ~]# kubectl get po -A
NAMESPACE      NAME                            READY   STATUS             RESTARTS        AGE
default        nginx-6768c68f7b-stz8j          1/1     Running            1 (8h ago)      13h
kube-flannel   kube-flannel-ds-wrg65           1/1     Running            1 (8h ago)      13h
kube-system    coredns-c676cc86f-6ftmz         1/1     Running            2 (8h ago)      2d9h
kube-system    coredns-c676cc86f-zwlr2         1/1     Running            2 (8h ago)      2d9h
kube-system    etcd-node4                      1/1     Running            3 (8h ago)      2d9h
kube-system    kube-apiserver-node4            1/1     Running            3 (8h ago)      2d9h
kube-system    kube-controller-manager-node4   1/1     Running            7 (3m39s ago)   2d9h
kube-system    kube-flannel-ds-gnqt2           0/1     CrashLoopBackOff   120 (36s ago)   14h
kube-system    kube-proxy-9dqdv                1/1     Running            3 (8h ago)      2d9h
kube-system    kube-scheduler-node4            1/1     Running            7 (3m39s ago)   2d9h

kubernetes集群证书备份功能的提取:

当然了,我这里做了一点优化,让输出更加好看一点,备份成功日志等级为info,整体为蓝色,如果有备份,日志等级为warning,输出带有红色。

可能我的美工不是太好,大家有兴趣可以自己调整输出的颜色。

#!/bin/bash
#!author zsk
set +x
set -o errexit
set -o pipefail
NC='\033[0m'
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
KUBE_PATH=/etc/kubernetes
log::info() {
  printf "[${BLUE}$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${YELLOW}INFO${NC}] %b\n" "$@"
}
log::warning() {
  printf "[$(date +'%Y-%m-%dT%H:%M:%S.%2N%z')][${RED}WARNING${NC}] \033[0m%b\n" "$@"
}
cert::backup_file() {
  local file=${1}
  if [[ ! -e ${file}.old-$(date +%Y%m%d) ]]; then
    cp -rp "${file}" "${file}.old-$(date +%Y%m%d)"
    log::info "${BLUE}backup ${file} to ${file}.old-$(date +%Y%m%d${NC})"
  else
    log::warning "does not backup, ${file}.old-$(date +%Y%m%d) already exists"
  fi
}
cert::backup_file "${KUBE_PATH}"

脚本执行的输出:

查看脚本运行成果,可以看到确实是智能的备份好了:

[root@node4 pki]# pwd
/etc/kubernetes.old-20221209/pki
[root@node4 pki]# ls
apiserver.crt              apiserver-etcd-client.key  apiserver-kubelet-client.crt  ca.crt  ca.srl  front-proxy-ca.crt  front-proxy-ca.srl      front-proxy-client.key  sa.pub
apiserver-etcd-client.crt  apiserver.key              apiserver-kubelet-client.key  ca.key  etcd    front-proxy-ca.key  front-proxy-client.crt  sa.key

当然了,这么一个脚本自然可以修改一哈,比如,MySQL数据库的物理文件备份,etcd数据库的物理文件备份等等都可以适用,如何改造我就不献丑了,大家可以发挥一哈聪明才智哦。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
26天前
|
Linux Shell
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
78 1
|
1月前
|
Linux 应用服务中间件 nginx
【PUSDN】centos查看日志文件内容,包含某个关键字的前后5行日志内容,centos查看日志的几种方法
【PUSDN】centos查看日志文件内容,包含某个关键字的前后5行日志内容,centos查看日志的几种方法
49 0
|
2月前
|
Prometheus 监控 Kubernetes
如何用 Prometheus Operator 监控 K8s 集群外服务?
如何用 Prometheus Operator 监控 K8s 集群外服务?
|
1月前
|
Prometheus 监控 Kubernetes
Kubernetes 集群监控与日志管理实践
【2月更文挑战第29天】 在微服务架构日益普及的当下,Kubernetes 已成为容器编排的事实标准。然而,随着集群规模的扩大和业务复杂度的提升,有效的监控和日志管理变得至关重要。本文将探讨构建高效 Kubernetes 集群监控系统的策略,以及实施日志聚合和分析的最佳实践。通过引入如 Prometheus 和 Fluentd 等开源工具,我们旨在为运维专家提供一套完整的解决方案,以保障系统的稳定性和可靠性。
|
22天前
|
关系型数据库 MySQL Linux
linux特定服务日志
Linux系统的服务日志在`/var/log`目录下,如系统日志(`/var/log/syslog`或`/var/log/messages`)、认证日志(`/var/log/auth.log`)、SSH日志(`/var/log/auth.log`或`/var/log/secure`)。Web服务器(Apache和Nginx)的访问和错误日志、MySQL错误日志、Postfix及Dovecot邮件服务器日志也在此处。日志位置可能因发行版和服务配置而异,不确定时可查服务配置或用`grep`搜索。使用`logrotate`可管理日志文件大小。
21 6
|
28天前
|
人工智能 监控 Serverless
如何基于ACK Serverless快速部署AI推理服务
通过上述步骤,可以在ACK Serverless上快速部署AI推理服务,实现高可用、弹性扩展的服务架构。
21 1
|
28天前
|
Kubernetes 网络协议 Docker
K8S核心插件-coredns服务
K8S核心插件-coredns服务
15 0
|
1月前
|
Prometheus 监控 Kubernetes
Kubernetes 集群的监控与日志管理实践
【2月更文挑战第31天】 在微服务架构日益普及的今天,容器编排工具如Kubernetes已成为部署、管理和扩展容器化应用的关键平台。然而,随着集群规模的扩大和业务复杂性的增加,如何有效监控集群状态、及时响应系统异常,以及管理海量日志信息成为了运维人员面临的重要挑战。本文将深入探讨 Kubernetes 集群监控的最佳实践和日志管理的高效策略,旨在为运维团队提供一套系统的解决思路和操作指南。
27 0
|
1月前
|
Kubernetes 应用服务中间件 nginx
Kubernetes服务网络Ingress网络模型分析、安装和高级用法
Kubernetes服务网络Ingress网络模型分析、安装和高级用法
36 5
|
1月前
|
域名解析 网络协议 应用服务中间件
nginx-ingress通过ipv6暴露服务,并在nginx ingress日志中记录客户端真实ipv6的ip地址
本文主要通过阿里云提供的clb和nlb来实现,建议是提前创建好双栈的vpc和vsw(使用clb可以不用双栈vpc和vsw)
189 1