前言:
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数据库的物理文件备份等等都可以适用,如何改造我就不献丑了,大家可以发挥一哈聪明才智哦。