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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 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数据库的物理文件备份等等都可以适用,如何改造我就不献丑了,大家可以发挥一哈聪明才智哦。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
1月前
|
Java Shell
「sh脚步模版自取」测试线排查的三个脚本:启动、停止、重启、日志保存
「sh脚步模版自取」测试线排查的三个脚本:启动、停止、重启、日志保存
36 1
|
3月前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
131 3
|
22天前
|
Kubernetes 监控 Cloud Native
|
1月前
|
负载均衡 Kubernetes 区块链
随机密码生成器+阿里k8s负载均衡型服务加证书方法+移动终端设计+ico生成器等
随机密码生成器+阿里k8s负载均衡型服务加证书方法+移动终端设计+ico生成器等
50 1
|
3月前
|
jenkins 持续交付
jenkins学习笔记之三:使用jenkins共享库实现日志格式化输出
jenkins学习笔记之三:使用jenkins共享库实现日志格式化输出
jenkins学习笔记之三:使用jenkins共享库实现日志格式化输出
|
2月前
|
缓存 监控 算法
分析慢日志文件来优化 PHP 脚本的性能
分析慢日志文件来优化 PHP 脚本的性能
|
3月前
|
Java Shell Linux
【Linux入门技巧】新员工必看:用Shell脚本轻松解析应用服务日志
关于如何使用Shell脚本来解析Linux系统中的应用服务日志,提供了脚本实现的详细步骤和技巧,以及一些Shell编程的技能扩展。
55 0
【Linux入门技巧】新员工必看:用Shell脚本轻松解析应用服务日志
|
3月前
|
运维 监控 数据可视化
自动化运维:使用Python脚本进行日志分析
【8月更文挑战第31天】当系统出现问题时,我们通常会查看日志寻找线索。然而,手动阅读大量日志既费时又易出错。本文将介绍如何使用Python脚本自动分析日志,快速定位问题,提高运维效率。我们将从简单的日志读取开始,逐步深入到复杂的正则表达式匹配和错误统计,最后实现一个自动化的日志监控系统。无论你是新手还是老手,这篇文章都将为你提供有价值的参考。让我们一起探索如何用代码解放双手,让运维工作变得更加轻松吧!
|
3月前
|
Kubernetes 算法 调度
在K8S中,如何把Pod调度到某个节点,有哪些方法?
在K8S中,如何把Pod调度到某个节点,有哪些方法?
|
11天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
117 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板