源码
sh
#!/bin/bash
# 作者:徐晓伟 xuxiaowei@xuxiaowei.com.cn
# 微信群:
# https://work.weixin.qq.com/gm/75cfc47d6a341047e4b6aca7389bdfa8
#
# 一键安装交互式页面:
# https://k8s-sh.xuxiaowei.com.cn
#
# 仓库:
# https://gitlab.xuxiaowei.com.cn/xuxiaowei-com-cn/k8s.sh
# https://gitee.com/xuxiaowei-com-cn/k8s.sh
# https://github.com/xuxiaowei-com-cn/k8s.sh
#
# 自动化测试流水线:
# https://gitlab.xuxiaowei.com.cn/xuxiaowei-com-cn/k8s.sh/-/pipelines
#
# 环境:
# https://gitlab.xuxiaowei.com.cn/xuxiaowei-com-cn/k8s.sh/-/environments/folders/kubernetes
#
# 如果发现脚本不能正常运行,可尝试执行:sed -i 's/\r$//' k8s.sh
#
# 代码格式使用:
# https://github.com/mvdan/sh
# 代码格式化命令:
# shfmt -l -w -i 2 k8s.sh
# 一旦有命令返回非零值,立即退出脚本
set -e
# 颜色定义
readonly COLOR_BLUE='\033[34m'
readonly COLOR_GREEN='\033[92m'
readonly COLOR_RED='\033[31m'
readonly COLOR_RESET='\033[0m'
readonly COLOR_YELLOW='\033[93m'
# 定义表情
readonly EMOJI_CONGRATS="\U0001F389"
readonly EMOJI_FAILURE="\U0001F61E"
# 文档简介链接
readonly DOCS_README_LINK=https://k8s-sh.xuxiaowei.com.cn/README.html
# 文档配置链接
readonly DOCS_CONFIG_LINK=https://k8s-sh.xuxiaowei.com.cn/config.html
# 查看系统类型、版本、内核
hostnamectl || true
# 当前系统类型,可能的值:
# almalinux
# anolis
# centos
# debian
# openEuler
# openkylin
# ubuntu
# uos
readonly os_type=$(grep -w "ID" /etc/os-release | cut -d'=' -f2 | tr -d '"')
echo -e "${COLOR_BLUE}系统类型: ${COLOR_GREEN}$os_type${COLOR_RESET}"
# 当前系统版本,可能的值:
# AlmaLinux: 8.10、9.4
# Anolis OS: 7.7、7.9、8.2、8.4、8.6、8.8、8.9、23
# CentOS: 7、8、9
# Debian: 10、11、12
# OpenEuler: 20.03、22.03、24.03
# OpenKylin: 1.0、1.0.1、1.0.2、2.0
# Ubuntu: 18.04、20.04、22.04、24.04
# UOS:
readonly os_version=$(grep -w "VERSION_ID" /etc/os-release | cut -d'=' -f2 | tr -d '"')
echo -e "${COLOR_BLUE}系统版本: ${COLOR_GREEN}$os_version${COLOR_RESET}"
readonly kylin_release_id=$(grep -w "KYLIN_RELEASE_ID" /etc/os-release | cut -d'=' -f2 | tr -d '"')
if [[ $kylin_release_id ]]; then
echo -e "${COLOR_BLUE}银河麒麟代码版本: ${COLOR_GREEN}$kylin_release_id${COLOR_RESET}"
fi
# 代码版本
readonly code_name=$(grep -w "VERSION_CODENAME" /etc/os-release | cut -d'=' -f2 | tr -d '"')
if [[ $code_name ]]; then
echo -e "${COLOR_BLUE}代码版本: ${COLOR_GREEN}$code_name${COLOR_RESET}"
fi
if [[ $os_type == 'centos' ]]; then
readonly centos_os_version=$(cat /etc/redhat-release | awk '{print $4}')
echo -e "${COLOR_BLUE}CentOS 系统具体版本: ${COLOR_GREEN}$centos_os_version${COLOR_RESET}"
fi
if [ -e "/etc/debian_version" ]; then
readonly debian_os_version=$(cat /etc/debian_version)
echo -e "${COLOR_BLUE}Debian 系统具体版本: ${COLOR_GREEN}$debian_os_version${COLOR_RESET}"
fi
# apt 锁超时时间
dpkg_lock_timeout=120
# Kubernetes 具体版本,包含: 主版本号、次版本号、修正版本号
kubernetes_version=v1.31.4
# Kubernetes 具体版本后缀
kubernetes_version_suffix=1.1
# Kubernetes 仓库
kubernetes_mirrors=("https://mirrors.aliyun.com/kubernetes-new/core/stable" "https://mirrors.tuna.tsinghua.edu.cn/kubernetes/core:/stable:" "https://pkgs.k8s.io/core:/stable:")
# Kubernetes 仓库: 默认仓库,取第一个
kubernetes_baseurl=${kubernetes_mirrors[0]}
# Kubernetes 镜像仓库
kubernetes_images_mirrors=("registry.aliyuncs.com/google_containers" "registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn" "registry.k8s.io")
# Kubernetes 镜像仓库: 默认仓库,取第一个
kubernetes_images=${kubernetes_images_mirrors[0]}
# pause 镜像
pause_image=${kubernetes_images_mirrors[0]}/pause
# Docker 仓库
docker_mirrors=("https://mirrors.aliyun.com/docker-ce/linux" "https://mirrors.cloud.tencent.com/docker-ce/linux" "https://download.docker.com/linux")
# Docker 仓库: 默认仓库,取第一个
docker_baseurl=${docker_mirrors[0]}
# 自定义 container-selinux 安装包,仅在少数系统中使用,如:OpenEuler 20.03
container_selinux_rpm=https://mirrors.aliyun.com/centos-altarch/7.9.2009/extras/i386/Packages/container-selinux-2.107-3.el7.noarch.rpm
# Docker 仓库类型
docker_repo_name=$os_type
# containerd 根路径
containerd_root=/var/lib/containerd
# containerd 运行状态路径
containerd_state=/run/containerd
case "$os_type" in
anolis | almalinux | openEuler | rocky)
docker_repo_name='centos'
;;
kylin | openkylin | Deepin)
docker_repo_name='debian'
;;
*) ;;
esac
calico_mirrors=("https://k8s-sh.xuxiaowei.com.cn/mirrors/projectcalico/calico" "https://gitlab.xuxiaowei.com.cn/mirrors/github.com/projectcalico/calico/-/raw" "https://raw.githubusercontent.com/projectcalico/calico/refs/tags")
calico_mirror=${calico_mirrors[0]}
calico_version=v3.29.0
calico_node_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/calico-node" "docker.io/calico/node")
calico_node_image=${calico_node_images[0]}
calico_cni_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/calico-cni" "docker.io/calico/cni")
calico_cni_image=${calico_cni_images[0]}
calico_kube_controllers_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/calico-kube-controllers" "docker.io/calico/kube-controllers")
calico_kube_controllers_image=${calico_kube_controllers_images[0]}
ingress_nginx_mirrors=("https://k8s-sh.xuxiaowei.com.cn/mirrors/kubernetes/ingress-nginx" "https://gitlab.xuxiaowei.com.cn/mirrors/github.com/kubernetes/ingress-nginx/-/raw" "https://raw.githubusercontent.com/kubernetes/ingress-nginx/refs/tags")
ingress_nginx_mirror=${ingress_nginx_mirrors[0]}
ingress_nginx_version=v1.11.3
ingress_nginx_controller_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/ingress-nginx-controller" "registry.k8s.io/ingress-nginx/controller")
ingress_nginx_controller_image=${ingress_nginx_controller_images[0]}
ingress_nginx_kube_webhook_certgen_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/ingress-nginx-kube-webhook-certgen" "registry.k8s.io/ingress-nginx/kube-webhook-certgen")
ingress_nginx_kube_webhook_certgen_image=${ingress_nginx_kube_webhook_certgen_images[0]}
metrics_server_version=v0.7.2
metrics_server_mirrors=("https://k8s-sh.xuxiaowei.com.cn/mirrors/kubernetes-sigs/metrics-server" "https://github.com/kubernetes-sigs/metrics-server/releases/download")
metrics_server_mirror=${metrics_server_mirrors[0]}
metrics_server_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/metrics-server" "registry.k8s.io/metrics-server/metrics-server")
metrics_server_image=${metrics_server_images[0]}
helm_version=v3.16.3
# https://mirrors.huaweicloud.com/helm/v3.16.3/helm-v3.16.3-linux-amd64.tar.gz
# https://get.helm.sh/helm-v3.16.3-linux-amd64.tar.gz
helm_mirrors=("https://mirrors.huaweicloud.com/helm" "https://get.helm.sh")
kubernetes_dashboard_charts=("http://k8s-sh.xuxiaowei.com.cn/charts/kubernetes/dashboard" "https://kubernetes.github.io/dashboard")
kubernetes_dashboard_chart=${kubernetes_dashboard_charts[0]}
kubernetes_dashboard_version=7.10.0
kubernetes_dashboard_auth_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/kubernetesui-dashboard-auth" "docker.io/kubernetesui/dashboard-auth")
kubernetes_dashboard_auth_image=${kubernetes_dashboard_auth_images[0]}
kubernetes_dashboard_api_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/kubernetesui-dashboard-api" "docker.io/kubernetesui/dashboard-api")
kubernetes_dashboard_api_image=${kubernetes_dashboard_api_images[0]}
kubernetes_dashboard_web_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/kubernetesui-dashboard-web" "docker.io/kubernetesui/dashboard-web")
kubernetes_dashboard_web_image=${kubernetes_dashboard_web_images[0]}
kubernetes_dashboard_metrics_scraper_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/kubernetesui-dashboard-metrics-scraper" "docker.io/kubernetesui/dashboard-metrics-scraper")
kubernetes_dashboard_metrics_scraper_image=${kubernetes_dashboard_metrics_scraper_images[0]}
kubernetes_dashboard_kong_images=("registry.cn-qingdao.aliyuncs.com/xuxiaoweicomcn/kong" "docker.io/library/kong")
kubernetes_dashboard_kong_image=${kubernetes_dashboard_kong_images[0]}
kubernetes_dashboard_ingress_enabled=true
kubernetes_dashboard_ingress_host=kubernetes.dashboard.xuxiaowei.com.cn
etcd_version=v3.5.17
etcd_mirrors=("https://mirrors.huaweicloud.com/etcd" "https://storage.googleapis.com/etcd" "https://github.com/etcd-io/etcd/releases/download")
etcd_mirror=${etcd_mirrors[0]}
etcd_client_port_2379=2379
etcd_peer_port_2380=2380
etcd_join_port=22
kernel_version=$(uname -r)
kernel_major_version=$(echo "$kernel_version" | cut -d. -f1)
kernel_minor_version=$(echo "$kernel_version" | cut -d. -f2)
echo -e "${COLOR_BLUE}系统内核版本: ${COLOR_GREEN}$kernel_version${COLOR_RESET}"
if [[ $kernel_major_version -le 4 && $kernel_minor_version -lt 19 ]]; then
# $(uname -r) < 4.19
echo -e "${COLOR_BLUE}可以安装 Kubernetes: ${COLOR_GREEN}v1.24.x ${COLOR_RESET}到${COLOR_GREEN} v1.31.x${COLOR_RESET}"
echo -e "${COLOR_YELLOW}无法安装 Kubernetes v1.32.x: ${COLOR_GREEN}v1.32.x 推荐最低内核为 4.19${COLOR_RESET}"
else
echo -e "${COLOR_BLUE}可以安装 Kubernetes: ${COLOR_GREEN}v1.24.x ${COLOR_RESET}到${COLOR_GREEN} v1.32.x${COLOR_RESET}"
fi
# 包管理类型
package_type=
case "$os_type" in
ubuntu | debian | kylin | openkylin | Deepin)
package_type=apt
;;
centos | anolis | almalinux | openEuler | rocky)
package_type=yum
;;
opensuse-leap)
package_type=zypper
;;
*)
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
;;
esac
_k8s_support_kernel() {
if [[ $kernel_major_version -le 4 && $kernel_minor_version -lt 19 ]]; then
# $(uname -r) < 4.19
kubernetes_minor_version=$(echo $kubernetes_version | cut -d. -f2)
if [[ $kubernetes_minor_version -ge 32 ]]; then
# $kubernetes_version >= v1.32.0
echo -e "${COLOR_RED}无法安装 Kubernetes $kubernetes_version,停止执行: ${COLOR_GREEN}v1.32.x 推荐最低内核为 4.19${COLOR_RESET}"
exit 1
fi
fi
}
_docker_repo() {
if [[ $package_type == 'yum' ]]; then
docker_gpgcheck=0
case "$docker_repo_type" in
"" | aliyun | tencent | docker)
docker_gpgcheck=1
;;
*) ;;
esac
sudo tee /etc/yum.repos.d/docker-ce.repo <<EOF
[docker-ce-stable]
name=Docker CE Stable - \$basearch
baseurl=$docker_baseurl/$docker_repo_name/\$releasever/\$basearch/stable
enabled=1
gpgcheck=$docker_gpgcheck
gpgkey=$docker_baseurl/$docker_repo_name/gpg
EOF
if [[ $os_type == 'anolis' ]]; then
case "$os_version" in
'23')
anolis_docker_version=8
echo -e "${COLOR_BLUE}$os_type $os_version 使用 $docker_repo_name $anolis_docker_version Docker 安装包${COLOR_RESET}"
sudo sed -i "s#\$releasever#$anolis_docker_version#" /etc/yum.repos.d/docker-ce.repo
;;
*) ;;
esac
fi
if [[ $os_type == 'openEuler' ]]; then
case "$os_version" in
'20.03' | '22.03' | '24.03')
openEuler_docker_version=8
echo -e "${COLOR_BLUE}$os_type $os_version 使用 $docker_repo_name $openEuler_docker_version Docker 安装包${COLOR_RESET}"
sudo sed -i "s#\$releasever#$openEuler_docker_version#" /etc/yum.repos.d/docker-ce.repo
;;
*) ;;
esac
fi
elif [[ $package_type == 'zypper' ]]; then
echo 'openSUSE 无需设置 Docker 仓库'
elif [[ $package_type == 'apt' ]]; then
sudo mkdir -p /etc/apt/sources.list.d
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL $docker_baseurl/$docker_repo_name/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] $docker_baseurl/$docker_repo_name \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
if [[ $os_type == 'openkylin' ]]; then
case "$code_name" in
yangtze | nile)
openkylin_docker_version=bookworm
echo -e "${COLOR_BLUE}$os_type $os_version $code_name 使用 $docker_repo_name $openkylin_docker_version Docker 安装包${COLOR_RESET}"
sed -i "s#$code_name#$openkylin_docker_version#" /etc/apt/sources.list.d/docker.list
;;
*) ;;
esac
fi
if [[ $os_type == 'kylin' ]]; then
case "$os_version" in
v10)
kylin_docker_version=bullseye
echo -e "${COLOR_BLUE}$os_type $os_version $code_name 使用 $docker_repo_name $kylin_docker_version Docker 安装包${COLOR_RESET}"
sed -i "s#$code_name#$kylin_docker_version#" /etc/apt/sources.list.d/docker.list
;;
*) ;;
esac
fi
if [[ $os_type == 'Deepin' ]]; then
case "$code_name" in
apricot)
deepin_docker_version=bullseye
echo -e "${COLOR_BLUE}$os_type $code_name $os_version 使用 $docker_repo_name $deepin_docker_version Docker 安装包${COLOR_RESET}"
sed -i "s#$code_name#$deepin_docker_version#" /etc/apt/sources.list.d/docker.list
;;
*) ;;
esac
fi
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}配置 Docker 源${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_remove_apt_ord_docker() {
case "$os_type" in
ubuntu)
if [[ $os_version == '18.04' ]]; then
for pkg in docker.io docker-doc docker-compose containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
elif [[ $os_version == '20.04' ]]; then
for pkg in docker.io docker-doc docker-compose docker-compose-v2 containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
else
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
fi
;;
openkylin)
if [[ $os_version == '1.0' || $os_version == '1.0.1' || $os_version == '1.0.2' ]]; then
for pkg in docker.io docker-doc docker-compose containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
else
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
fi
;;
debian)
if [[ $os_version == '10' ]]; then
for pkg in docker.io docker-doc docker-compose containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
elif [[ $os_version == '11' ]]; then
for pkg in docker.io docker-doc docker-compose containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
else
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
fi
;;
Deepin)
if [[ $os_version == '20.9' ]]; then
for pkg in docker.io docker-doc docker-compose containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
else
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
fi
;;
kylin)
if [[ $os_version == 'v10' ]]; then
for pkg in docker.io docker-doc docker-compose containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
else
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout remove -y $pkg; done
fi
;;
*)
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}卸载旧版 Docker${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
;;
esac
}
_containerd_install() {
if [[ $package_type == 'yum' ]]; then
sudo yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
if [[ $os_type == 'openEuler' && $os_version == '20.03' ]]; then
echo -e "${COLOR_BLUE}$os_type $os_version 安装 ${COLOR_GREEN}$container_selinux_rpm${COLOR_RESET}"
sudo yum install -y $container_selinux_rpm
fi
sudo yum install -y containerd.io
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install containerd
elif [[ $package_type == 'apt' ]]; then
_remove_apt_ord_docker
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y containerd.io
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 Containerd${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
sudo systemctl start containerd
sudo systemctl status containerd -l --no-pager
sudo systemctl enable containerd
}
# 容器运行时
# https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/
# https://kubernetes.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/
_containerd_config() {
sudo mkdir -p /etc/containerd/certs.d
containerd_config_backup_path=/etc/containerd/config.toml.$(date +%Y%m%d%H%M%S)
echo -e "${COLOR_BLUE}containerd 备份历史配置路径: ${COLOR_GREEN}$containerd_config_backup_path${COLOR_RESET}"
sudo cp /etc/containerd/config.toml $containerd_config_backup_path || true
sudo containerd config default | sudo tee /etc/containerd/config.toml
echo -e "${COLOR_BLUE}containerd 根路径: ${COLOR_GREEN}$containerd_root${COLOR_RESET}"
sed -i "s#^root = \".*\"#root = \"$containerd_root\"#" /etc/containerd/config.toml
echo -e "${COLOR_BLUE}containerd 运行状态路径: ${COLOR_GREEN}$containerd_state${COLOR_RESET}"
sed -i "s#^state = \".*\"#state = \"$containerd_state\"#" /etc/containerd/config.toml
# 兼容 OpenKylin 2.0,防止在 /etc/containerd/config.toml 生成无关配置
if [[ $os_type == 'openkylin' && $os_version == '2.0' ]]; then
echo -e "${COLOR_BLUE}$os_type $os_version 注释 /etc/containerd/config.toml 无用配置${COLOR_RESET}"
sudo sed -i 's/^User/#&/' /etc/containerd/config.toml
fi
echo -e "${COLOR_BLUE}containerd 配置中,registry.k8s.io/pause 使用: ${COLOR_GREEN}$pause_image ${COLOR_BLUE}镜像${COLOR_RESET}"
sudo sed -i "s#registry.k8s.io/pause#$pause_image#g" /etc/containerd/config.toml
echo -e "${COLOR_BLUE}containerd 配置中,SystemdCgroup 设置为: ${COLOR_GREEN}true ${COLOR_RESET}"
sudo sed -i "s#SystemdCgroup = false#SystemdCgroup = true#g" /etc/containerd/config.toml
echo -e "${COLOR_BLUE}containerd 配置中,certs 文件夹设置为: ${COLOR_GREEN}/etc/containerd/certs.d${COLOR_RESET}"
sudo sed -i "s#config_path = \"\"#config_path = \"/etc/containerd/certs.d\"#" /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl status containerd -l --no-pager
sudo systemctl enable containerd
}
_docker_install() {
if [[ $package_type == 'yum' ]]; then
sudo yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
if [[ $os_type == 'openEuler' && $os_version == '20.03' ]]; then
echo -e "${COLOR_BLUE}$os_type $os_version 安装 ${COLOR_GREEN}$container_selinux_rpm${COLOR_RESET}"
fi
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install docker
elif [[ $package_type == 'apt' ]]; then
_remove_apt_ord_docker
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 Docker${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
sudo systemctl restart docker.socket
sudo systemctl restart docker.service
sudo systemctl status docker.socket -l --no-pager
sudo systemctl status docker.service -l --no-pager
sudo systemctl enable docker.socket
sudo systemctl enable docker.service
sudo docker info
sudo docker ps
sudo docker images
}
_socat() {
if [[ $package_type == 'yum' ]]; then
sudo yum -y install socat
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install socat
elif [[ $package_type == 'apt' ]]; then
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y socat
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 socat${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_iproute() {
if [[ $package_type == 'yum' ]]; then
if [[ $os_type == 'anolis' ]]; then
case "$os_version" in
'7.7' | '7.9')
sudo yum -y install iproute
;;
*)
sudo yum -y install iproute-tc
;;
esac
elif [[ $os_type == 'centos' ]]; then
case "$centos_os_version" in
'7.9.2009')
sudo yum -y install iproute
;;
*)
sudo yum -y install iproute-tc
;;
esac
else
sudo yum -y install iproute-tc
fi
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install iproute2
elif [[ $package_type == 'apt' ]]; then
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y iproute2
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 iproute-tc、iproute2${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_kubernetes_repo() {
_k8s_support_kernel
# Kubernetes 仓库版本号,包含: 主版本号、次版本号
kubernetes_repo_version=$(echo $kubernetes_version | cut -d. -f1-2)
if [[ $package_type == 'yum' ]]; then
kubernetes_gpgcheck=0
case "$kubernetes_repo_type" in
"" | aliyun | tsinghua | kubernetes)
echo -e "${COLOR_BLUE}开启了 gpg 检查${COLOR_RESET}"
kubernetes_gpgcheck=1
;;
*)
echo -e "${COLOR_BLUE}未开启 gpg 检查${COLOR_RESET}"
;;
esac
sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=$kubernetes_baseurl/$kubernetes_repo_version/rpm/
enabled=1
gpgcheck=$kubernetes_gpgcheck
gpgkey=$kubernetes_baseurl/$kubernetes_repo_version/rpm/repodata/repomd.xml.key
EOF
elif [[ $package_type == 'zypper' ]]; then
sudo tee /etc/zypp/repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=$kubernetes_baseurl/$kubernetes_repo_version/rpm/
enabled=1
gpgcheck=0
gpgkey=$kubernetes_baseurl/$kubernetes_repo_version/rpm/repodata/repomd.xml.key
EOF
elif [[ $package_type == 'apt' ]]; then
sudo mkdir -p /etc/apt/sources.list.d
case "$kubernetes_repo_type" in
"" | aliyun | tsinghua | kubernetes)
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL $kubernetes_baseurl/$kubernetes_repo_version/deb/Release.key -o /etc/apt/keyrings/kubernetes.asc
sudo chmod a+r /etc/apt/keyrings/kubernetes.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/kubernetes.asc] $kubernetes_baseurl/$kubernetes_repo_version/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list >/dev/null
;;
*)
echo \
"deb [arch=$(dpkg --print-architecture) trusted=yes] $kubernetes_baseurl/$kubernetes_repo_version/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list >/dev/null
;;
esac
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}配置 Kubernetes 源${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_swap_off() {
free -h
sudo swapoff -a
free -h
cat /etc/fstab
sudo sed -i 's/.*swap.*/#&/' /etc/fstab
cat /etc/fstab
}
_curl() {
if [[ $package_type == 'yum' ]]; then
sudo yum -y install curl
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install curl
elif [[ $package_type == 'apt' ]]; then
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y curl
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 curl${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_ca_certificates() {
if [[ $package_type == 'yum' ]]; then
sudo yum -y install ca-certificates
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install ca-certificates
elif [[ $package_type == 'apt' ]]; then
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y ca-certificates
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 ca-certificates${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_kubernetes_install() {
_k8s_support_kernel
version=${kubernetes_version:1}
if [[ $package_type == 'yum' ]]; then
sudo yum install -y kubelet-"$version" kubeadm-"$version" kubectl-"$version"
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install kubelet-"$version" kubeadm-"$version" kubectl-"$version"
elif [[ $package_type == 'apt' ]]; then
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y kubelet="$version"-$kubernetes_version_suffix kubeadm="$version"-$kubernetes_version_suffix kubectl="$version"-$kubernetes_version_suffix
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}安装 Kubernetes${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_kubernetes_images_pull() {
kubeadm config images list --image-repository="$kubernetes_images" --kubernetes-version="$kubernetes_version"
kubeadm config images pull --image-repository="$kubernetes_images" --kubernetes-version="$kubernetes_version"
}
# 启用 IPv4 数据包转发
# https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/
# https://kubernetes.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/
_enable_ipv4_packet_forwarding() {
# Kubernetes 版本号,包含: 主版本号、次版本号
kubernetes_version_tmp=$(echo $kubernetes_version | cut -d. -f1-2)
ipv4_ip_forward=$(grep -w "net.ipv4.ip_forward" /etc/sysctl.conf | cut -d'=' -f2 | tr -d ' ')
if [[ $ipv4_ip_forward == '0' ]]; then
echo -e "${COLOR_YELLOW}/etc/sysctl.conf 文件中关闭了 net.ipv4.ip_forward,将注释此配置${COLOR_RESET}"
# 如果 IPv4 数据包转发 已关闭: 注释已存在的配置,防止冲突
sudo sed -i 's|net.ipv4.ip_forward|#net.ipv4.ip_forward|g' /etc/sysctl.conf
fi
ipv4_ip_forward=$(grep -w "net.ipv4.ip_forward" /etc/sysctl.d/99-sysctl.conf | cut -d'=' -f2 | tr -d ' ')
if [[ $ipv4_ip_forward == '0' ]]; then
echo -e "${COLOR_YELLOW}/etc/sysctl.d/99-sysctl.conf 文件中关闭了 net.ipv4.ip_forward,将注释此配置${COLOR_RESET}"
# 如果 IPv4 数据包转发 已关闭: 注释已存在的配置,防止冲突
sudo sed -i 's|net.ipv4.ip_forward|#net.ipv4.ip_forward|g' /etc/sysctl.d/99-sysctl.conf
fi
case "$kubernetes_version_tmp" in
"v1.24" | "v1.25" | "v1.26" | "v1.27" | "v1.28" | "v1.29")
# https://kubernetes-v1-24.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# https://kubernetes-v1-25.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# https://kubernetes-v1-26.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# https://kubernetes-v1-27.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# https://kubernetes-v1-28.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# https://kubernetes-v1-29.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
lsmod | grep br_netfilter
lsmod | grep overlay
;;
*)
# https://kubernetes-v1-30.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# https://kubernetes-v1-31.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/container-runtimes/#install-and-configure-prerequisites
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
;;
esac
}
_kubernetes_config() {
_enable_ipv4_packet_forwarding
_socat
_iproute
systemctl enable kubelet.service
}
_kubernetes_init_congrats() {
echo
echo
echo
echo -e "${COLOR_BLUE}${EMOJI_CONGRATS}${EMOJI_CONGRATS}${EMOJI_CONGRATS}${COLOR_RESET}"
echo -e "${COLOR_BLUE}Kubernetes 已完成安装${COLOR_RESET}"
echo
echo -e "${COLOR_BLUE}请选择下列方式之一,重载环境变量后,即可直接控制 Kubernetes${COLOR_RESET}"
echo
echo -e "${COLOR_BLUE}1. 执行命令刷新环境变量:"
echo -e "\t${COLOR_GREEN}source /etc/profile${COLOR_RESET}"
echo -e "\t${COLOR_GREEN}source /etc/bash_completion.d/kubectl${COLOR_RESET}"
echo
echo -e "${COLOR_BLUE}2. 重新连接 SSH${COLOR_RESET}"
echo
echo
echo
}
_k8s_init_pre_config_etcd() {
etcd_external_num=0
if [[ $etcd_ips ]]; then
etcd_external_num=$(($etcd_external_num + 1))
fi
if [[ $etcd_cafile ]]; then
etcd_external_num=$(($etcd_external_num + 1))
fi
if [[ $etcd_certfile ]]; then
etcd_external_num=$(($etcd_external_num + 1))
fi
if [[ $etcd_keyfile ]]; then
etcd_external_num=$(($etcd_external_num + 1))
fi
if [[ $etcd_external_num -gt 0 && $etcd_external_num -lt 4 ]]; then
echo -e "${COLOR_RED}kubernetes 初始化 使用外部 ETCD 时,etcd 参数不完整${COLOR_RESET}"
echo -e "${COLOR_RED}kubernetes 使用外部 ETCD 完整参数至少包含:${COLOR_GREEN}etcd-ips${COLOR_RESET}、${COLOR_GREEN}etcd-cafile${COLOR_RESET}、${COLOR_GREEN}etcd-certfile${COLOR_RESET}、${COLOR_GREEN}etcd-keyfile${COLOR_RESET}"
echo -e "${COLOR_RED}kubernetes 不使用外部 ETCD 时,请不要包含下列参数:${COLOR_GREEN}etcd-ips${COLOR_RESET}、${COLOR_GREEN}etcd-cafile${COLOR_RESET}、${COLOR_GREEN}etcd-certfile${COLOR_RESET}、${COLOR_GREEN}etcd-keyfile${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看配置: ${COLOR_GREEN}${DOCS_CONFIG_LINK}${COLOR_RESET}"
exit 1
elif [ $etcd_external_num == 4 ]; then
echo "etcd:" >>kubeadm-config.yaml
echo " external:" >>kubeadm-config.yaml
echo " caFile: $etcd_cafile" >>kubeadm-config.yaml
echo " certFile: $etcd_certfile" >>kubeadm-config.yaml
echo " keyFile: $etcd_keyfile" >>kubeadm-config.yaml
echo " endpoints:" >>kubeadm-config.yaml
for etcd_ip in "${etcd_ips[@]}"; do
echo " - https://$etcd_ip:$etcd_client_port_2379" >>kubeadm-config.yaml
done
fi
}
_kubernetes_init() {
if [[ $kubernetes_init_node_name ]]; then
kubernetes_init_node_name="--node-name=$kubernetes_init_node_name"
fi
if [[ $control_plane_endpoint ]]; then
control_plane_endpoint="controlPlaneEndpoint: $control_plane_endpoint"
fi
if [[ $service_cidr ]]; then
service_cidr="serviceSubnet: $service_cidr"
fi
if [[ $pod_network_cidr ]]; then
pod_network_cidr="podSubnet: $pod_network_cidr"
fi
kubeadm_apiVersion=$(kubeadm config print init-defaults | head -n 1)
cat <<EOF | sudo tee kubeadm-config.yaml
$kubeadm_apiVersion
kind: ClusterConfiguration
kubernetesVersion: $kubernetes_version
$control_plane_endpoint
# 证书有效期:100年(此配置仅支持 kubernetes v1.31.0+)
caCertificateValidityPeriod: 876000h0m0s
# 证书有效期:100年(此配置仅支持 kubernetes v1.31.0+)
certificateValidityPeriod: 876000h0m0s
imageRepository: $kubernetes_images
networking:
dnsDomain: cluster.local
$service_cidr
$pod_network_cidr
EOF
_k8s_init_pre_config_etcd
kubeadm init $kubernetes_init_node_name --config=kubeadm-config.yaml
KUBECONFIG=$(grep -w "KUBECONFIG" /etc/profile | cut -d'=' -f2)
if [[ $KUBECONFIG != '/etc/kubernetes/admin.conf' ]]; then
sudo sed -i 's/.*KUBECONFIG.*/#&/' /etc/profile
echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >>/etc/profile
fi
# 此处兼容 AnolisOS 23.1,防止退出
source /etc/profile || true
echo -e "${COLOR_BLUE}查看集群配置: ${COLOR_GREEN}kubectl -n kube-system get cm kubeadm-config -o yaml${COLOR_RESET}"
kubectl -n kube-system get cm kubeadm-config -o yaml
echo -e "${COLOR_BLUE}查看证书有效期: ${COLOR_GREEN}kubeadm certs check-expiration${COLOR_RESET}"
kubeadm certs check-expiration
echo -e "${COLOR_BLUE}查看集群节点信息: ${COLOR_GREEN}kubectl get node -o wide${COLOR_RESET}"
kubectl get node -o wide
echo -e "${COLOR_BLUE}查看集群 Service: ${COLOR_GREEN}kubectl get svc -A -o wide${COLOR_RESET}"
kubectl get svc -A -o wide
echo -e "${COLOR_BLUE}查看集群 Pod: ${COLOR_GREEN}kubectl get pod -A -o wide${COLOR_RESET}"
kubectl get pod -A -o wide
if [[ $standalone == true ]]; then
# 单机模式,在下方 $standalone == true 时执行 _kubernetes_init_congrats
echo
elif [[ $cluster == true ]]; then
# 集群模式,在下方 $cluster == true 时执行 _kubernetes_init_congrats
echo
elif [[ $node == true ]]; then
# 工作节点准备,不执行 _kubernetes_init_congrats
echo
else
_kubernetes_init_congrats
fi
}
_kubernetes_taint() {
kubectl get nodes -o wide
kubectl get pod -A -o wide
kubectl get node -o yaml | grep taint -A 10
kubernetes_version_tmp=$(echo $kubernetes_version | cut -d. -f1-2)
if [[ $kubernetes_version_tmp == 'v1.24' ]]; then
kubectl taint nodes --all node-role.kubernetes.io/master- || true
kubectl taint nodes --all node-role.kubernetes.io/control-plane- || true
else
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
fi
kubectl get node -o yaml | grep taint -A 10 | true
kubectl get nodes -o wide
kubectl get pod -A -o wide
}
_print_join_command() {
kubeadm token create --print-join-command
}
_bash_completion() {
if [[ $package_type == 'yum' ]]; then
sudo yum -y install bash-completion
# 此处兼容 AnolisOS 23.1,防止退出
source /etc/profile || true
elif [[ $package_type == 'zypper' ]]; then
sudo zypper -n install bash-completion
# 此处兼容 openSUSE Leap 15.6,防止退出
source /etc/profile || true
elif [[ $package_type == 'apt' ]]; then
sudo apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y bash-completion
# 此处兼容 Debian 11.7.0,防止退出
source /etc/profile || true
fi
}
# kubectl 的可选配置和插件
# 启用 shell 自动补全功能
# https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-linux/#optional-kubectl-configurations
# https://kubernetes.xuxiaowei.com.cn/zh-cn/docs/tasks/tools/install-kubectl-linux/#optional-kubectl-configurations
_enable_shell_autocompletion() {
_bash_completion
if [[ $package_type == 'yum' || $package_type == 'zypper' || $package_type == 'apt' ]]; then
sudo mkdir -p /etc/bash_completion.d
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl >/dev/null
sudo chmod a+r /etc/bash_completion.d/kubectl
source /etc/bash_completion.d/kubectl
else
echo -e "${COLOR_RED}不支持的发行版: ${COLOR_GREEN}$os_type ${COLOR_RED}启用 shell 自动补全功能${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看已支持的发行版: ${COLOR_GREEN}$DOCS_README_LINK${COLOR_RESET}"
exit 1
fi
}
_interface_name() {
if ! [[ $interface_name ]]; then
interface_name=$(ip route get 223.5.5.5 | grep -oP '(?<=dev\s)\w+' | head -n 1)
if [[ "$interface_name" ]]; then
echo -e "${COLOR_BLUE}上网网卡是 ${COLOR_RESET}${COLOR_GREEN}${interface_name}${COLOR_RESET}"
else
echo -e "${COLOR_RED}未找到上网网卡,停止安装${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看网卡配置 interface-name: ${COLOR_GREEN}${DOCS_CONFIG_LINK}#interface-name${COLOR_RESET}"
exit 1
fi
fi
}
_calico_install() {
if ! [[ $calico_url ]]; then
calico_url=$calico_mirror/$calico_version/manifests/calico.yaml
fi
echo -e "${COLOR_BLUE}calico manifests url: ${COLOR_GREEN}$calico_url${COLOR_RESET}"
calico_local_path=calico.yaml
if [[ $calico_url =~ ^https?:// ]]; then
curl -k -o $calico_local_path $calico_url
else
calico_local_path=$calico_url
fi
if grep -q "interface=" "$calico_local_path"; then
echo -e "${COLOR_BLUE}已配置 calico 使用的网卡,脚本跳过网卡配置${COLOR_RESET}"
else
_interface_name
sed -i '/k8s,bgp/a \ - name: IP_AUTODETECTION_METHOD\n value: "interface=INTERFACE_NAME"' $calico_local_path
sed -i "s#INTERFACE_NAME#$interface_name#g" $calico_local_path
fi
sed -i "s#${calico_node_images[-1]}#$calico_node_image#g" $calico_local_path
sed -i "s#${calico_cni_images[-1]}#$calico_cni_image#g" $calico_local_path
sed -i "s#${calico_kube_controllers_images[-1]}#$calico_kube_controllers_image#g" $calico_local_path
kubectl apply -f $calico_local_path
kubectl get pod -A -o wide
if [[ $cluster != true ]]; then
kubectl wait --for=condition=Ready --all pods -A --timeout=300s || true
fi
}
_ingress_nginx_install() {
if ! [[ $ingress_nginx_url ]]; then
ingress_nginx_url=$ingress_nginx_mirror/controller-$ingress_nginx_version/deploy/static/provider/cloud/deploy.yaml
fi
echo -e "${COLOR_BLUE}ingress nginx manifests url: ${COLOR_GREEN}$ingress_nginx_url${COLOR_RESET}"
ingress_nginx_local_path=ingress_nginx.yaml
if [[ $ingress_nginx_url =~ ^https?:// ]]; then
curl -k -o $ingress_nginx_local_path $ingress_nginx_url
else
ingress_nginx_local_path=$ingress_nginx_url
fi
sudo sed -i 's/@.*$//' $ingress_nginx_local_path
sudo sed -i "s#${ingress_nginx_controller_images[-1]}#$ingress_nginx_controller_image#g" $ingress_nginx_local_path
sudo sed -i "s#${ingress_nginx_kube_webhook_certgen_images[-1]}#$ingress_nginx_kube_webhook_certgen_image#g" $ingress_nginx_local_path
kubectl apply -f $ingress_nginx_local_path
kubectl get pod -A -o wide
}
_ingress_nginx_host_network() {
kubectl -n ingress-nginx patch deployment ingress-nginx-controller --patch '{"spec": {"template": {"spec": {"hostNetwork": true}}}}'
}
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#allow-snippet-annotations
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#stream-snippet
# https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#configuration-snippet
# CVE-2021-25742:https://github.com/kubernetes/kubernetes/issues/126811
_ingress_nginx_allow_snippet_annotations() {
kubectl -n ingress-nginx patch configmap ingress-nginx-controller --type merge -p '{"data":{"allow-snippet-annotations":"true"}}'
}
_metrics_server_install() {
if ! [[ $metrics_server_url ]]; then
metrics_server_url=$metrics_server_mirror/$metrics_server_version/components.yaml
fi
echo -e "${COLOR_BLUE}metrics server manifests url: ${COLOR_GREEN}$metrics_server_url${COLOR_RESET}"
metrics_server_local_path=metrics_server.yaml
if [[ $metrics_server_url =~ ^https?:// ]]; then
curl -k -o $metrics_server_local_path $metrics_server_url
else
metrics_server_local_path=$metrics_server_url
fi
sudo sed -i "s#${metrics_server_images[-1]}#$metrics_server_image#g" $metrics_server_local_path
if [[ $metrics_server_secure_tls != true ]]; then
sed -i '/- args:/a \ \ \ \ \ \ \ \ - --kubelet-insecure-tls' $metrics_server_local_path
fi
kubectl apply -f $metrics_server_local_path
kubectl get pod -A -o wide
}
_tar_install() {
if ! command -v 'tar' &>/dev/null; then
if [[ $package_type == 'yum' ]]; then
echo -e "${COLOR_BLUE}tar 未安装,正在安装...${COLOR_RESET}"
sudo yum install -y tar
echo -e "${COLOR_BLUE}tar 安装完成${COLOR_RESET}"
elif [[ $package_type == 'apt' ]]; then
echo -e "${COLOR_BLUE}tar 未安装,正在安装...${COLOR_RESET}"
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y tar
echo -e "${COLOR_BLUE}tar 安装完成${COLOR_RESET}"
fi
fi
}
_helm_install() {
if ! [[ $helm_url ]]; then
case "$helm_repo_type" in
"" | huawei)
helm_url=${helm_mirrors[0]}/$helm_version/helm-$helm_version-linux-amd64.tar.gz
;;
helm)
helm_url=${helm_mirrors[-1]}/helm-$helm_version-linux-amd64.tar.gz
;;
*) ;;
esac
fi
echo -e "${COLOR_BLUE}helm url: ${COLOR_GREEN}$helm_url${COLOR_RESET}"
helm_local_path=helm-$helm_version-linux-amd64.tar.gz
helm_local_folder=helm-$helm_version-linux-amd64
if [[ $helm_url =~ ^https?:// ]]; then
curl -k -o $helm_local_path $helm_url
else
helm_local_path=$helm_url
fi
_tar_install
mkdir -p $helm_local_folder
tar -zxvf $helm_local_path --strip-components=1 -C $helm_local_folder
$helm_local_folder/helm version
cp $helm_local_folder/helm /usr/local/bin/helm
/usr/local/bin/helm version
/usr/local/bin/helm ls -A
}
# https://github.com/kubernetes/dashboard?tab=readme-ov-file#installation
# https://github.com/kubernetes/dashboard/blob/master/charts/kubernetes-dashboard/values.yaml
# https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md
_helm_install_kubernetes_dashboard() {
echo -e "${COLOR_BLUE}准备清理已存在的 kubernetes-dashboard charts 仓库 ...${COLOR_RESET}"
helm repo remove kubernetes-dashboard || echo -e "${COLOR_BLUE}本地未安装 kubernetes-dashboard 仓库${COLOR_RESET}"
echo -e "${COLOR_BLUE}准备安装 kubernetes-dashboard charts 仓库: ${COLOR_GREEN}$kubernetes_dashboard_chart${COLOR_RESET}"
helm repo add kubernetes-dashboard $kubernetes_dashboard_chart
echo -e "${COLOR_BLUE}准备生成 kubernetes-dashboard charts 仓库安装配置 ...${COLOR_RESET}"
cat <<EOF | sudo tee kubernetes_dashboard.yml
app:
ingress:
enabled: $kubernetes_dashboard_ingress_enabled
hosts:
- localhost
- $kubernetes_dashboard_ingress_host
# Default: internal-nginx
ingressClassName: nginx
auth:
image:
repository: $kubernetes_dashboard_auth_image
api:
image:
repository: $kubernetes_dashboard_api_image
web:
image:
repository: $kubernetes_dashboard_web_image
metricsScraper:
image:
repository: $kubernetes_dashboard_metrics_scraper_image
kong:
image:
repository: $kubernetes_dashboard_kong_image
EOF
echo -e "${COLOR_BLUE}准备使用自定义配置安装 kubernetes-dashboard charts ...${COLOR_RESET}"
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard --version $kubernetes_dashboard_version -f kubernetes_dashboard.yml
echo -e "${COLOR_BLUE}准备生成 kubernetes-dashboard service account yml ...${COLOR_RESET}"
cat <<EOF | sudo tee kubernetes_dashboard_service_account.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
EOF
echo -e "${COLOR_BLUE}准备生成 kubernetes-dashboard cluster role binding yml ...${COLOR_RESET}"
cat <<EOF | sudo tee kubernetes_dashboard_cluster_role_binding.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF
echo -e "${COLOR_BLUE}准备生成 kubernetes-dashboard secret yml ...${COLOR_RESET}"
cat <<EOF | sudo tee kubernetes_dashboard_secret.yml
apiVersion: v1
kind: Secret
metadata:
name: admin-user
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: "admin-user"
type: kubernetes.io/service-account-token
EOF
echo -e "${COLOR_BLUE}准备创建 kubernetes-dashboard service account yml ...${COLOR_RESET}"
kubectl apply -f kubernetes_dashboard_service_account.yml
echo -e "${COLOR_BLUE}准备创建 kubernetes-dashboard cluster role binding yml ...${COLOR_RESET}"
kubectl apply -f kubernetes_dashboard_cluster_role_binding.yml
echo -e "${COLOR_BLUE}准备创建 kubernetes-dashboard secret yml ...${COLOR_RESET}"
kubectl apply -f kubernetes_dashboard_secret.yml
echo -e "${COLOR_BLUE}准备创建 kubernetes-dashboard token(默认有效期 1h) ...${COLOR_RESET}"
echo -e "${COLOR_BLUE}使用: ${COLOR_GREEN}kubectl -n kubernetes-dashboard create token admin-user --duration=86400s ${COLOR_BLUE}创建指定有效时间的 token${COLOR_RESET}"
echo -e "${COLOR_BLUE}使用: ${COLOR_GREEN}kubectl -n kubernetes-dashboard get secret admin-user -o jsonpath={".data.token"} | base64 -d ${COLOR_BLUE}获取长期 token${COLOR_RESET}"
echo ''
kubectl -n kubernetes-dashboard create token admin-user
echo ''
}
_firewalld_stop() {
if [[ $package_type == 'yum' || $package_type == 'zypper' ]]; then
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
fi
}
_selinux_disabled() {
if [[ $package_type == 'yum' ]]; then
getenforce
sudo setenforce 0 || true
sudo getenforce
cat /etc/selinux/config
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
cat /etc/selinux/config
fi
}
_etcd_binary_install() {
_firewalld_stop
mkdir -p /root/.ssh
mkdir -p /etc/etcd/pki
if ! [[ $etcd_current_ip ]]; then
etcd_current_ip=$(hostname -I | awk '{print $1}')
fi
# 当存在 etcd_ips 参数时,当前机器的 IP 必须在 etcd_ips 参数内
if [[ $etcd_ips ]]; then
if ! [[ "${etcd_ips[*]}" =~ ${etcd_current_ip} ]]; then
echo "当前机器的 IP: $etcd_current_ip 不在 etcd 集群 IP 列表中,终止 etcd 安装"
for etcd_ip in "${etcd_ips[@]}"; do
echo "$etcd_ip"
done
exit 1
fi
fi
# etcd_ips 参数的个数
etcd_ips_length=${#etcd_ips[@]}
# etcd_ips 参数中 @ 的数量
etcd_ips_at_num=0
# etcd_ips 参数中,自定义的 ETCD 节点 名称
etcd_ips_names=()
# etcd_ips 参数中,自定义的 ETCD 节点 IP
etcd_ips_tmp=()
for etcd_ip in "${etcd_ips[@]}"; do
etcd_ip_tmp=$(echo $etcd_ip | awk -F'@' '{print $1}')
etcd_ip_name_tmp=$(echo $etcd_ip | awk -F'@' '{print $2}')
if [[ $etcd_ip_name_tmp ]]; then
etcd_ips_names+=("$etcd_ip_name_tmp")
etcd_ips_at_num=$(($etcd_ips_at_num + 1))
fi
etcd_ips_tmp+=("$etcd_ip_tmp")
done
if [[ $etcd_ips_at_num != 0 && "$etcd_ips_at_num" != "$etcd_ips_length" ]]; then
echo "ETCD 名称配置错误:只能全部忽略名称或全部自定义名称"
echo "etcd_ips: ${etcd_ips[*]}"
exit 1
fi
etcd_ips=("${etcd_ips_tmp[@]}")
etcd_ips_names_length=${#etcd_ips_names[@]}
echo "当前 etcd 节点的 IP: $etcd_current_ip"
echo "etcd 集群配置:"
local etcd_num=0
etcd_initial_cluster=''
for etcd_ip in "${etcd_ips[@]}"; do
etcd_num=$(($etcd_num + 1))
if [[ $etcd_ips_names_length == 0 ]]; then
etcd_name="etcd-$etcd_num"
else
etcd_name="${etcd_ips_names[$etcd_num - 1]}"
fi
echo "$etcd_name: $etcd_ip:$etcd_client_port_2379"
etcd_initial_cluster+=$etcd_name=https://$etcd_ip:$etcd_peer_port_2380,
done
etcd_initial_cluster="${etcd_initial_cluster%,}"
_tar_install
if ! [[ $etcd_url ]]; then
etcd_url=$etcd_mirror/$etcd_version/etcd-$etcd_version-linux-amd64.tar.gz
fi
echo "etcd_url=$etcd_url"
curl -L "${etcd_url}" -o etcd-${etcd_version}-linux-amd64.tar.gz
tar xzvf etcd-${etcd_version}-linux-amd64.tar.gz
etcd-${etcd_version}-linux-amd64/etcd --version
etcd-${etcd_version}-linux-amd64/etcdctl version
etcd-${etcd_version}-linux-amd64/etcdutl version
cp etcd-${etcd_version}-linux-amd64/etcd /usr/local/bin/
cp etcd-${etcd_version}-linux-amd64/etcdctl /usr/local/bin/
cp etcd-${etcd_version}-linux-amd64/etcdutl /usr/local/bin/
/usr/local/bin/etcd --version
/usr/local/bin/etcdctl version
/usr/local/bin/etcdutl version
if ! command -v 'openssl' &>/dev/null; then
if [[ $package_type == 'yum' ]]; then
echo -e "${COLOR_BLUE}openssl 未安装,正在安装...${COLOR_RESET}"
sudo yum install -y openssl
echo -e "${COLOR_BLUE}openssl 安装完成${COLOR_RESET}"
elif [[ $package_type == 'apt' ]]; then
echo -e "${COLOR_BLUE}openssl 未安装,正在安装...${COLOR_RESET}"
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y openssl
echo -e "${COLOR_BLUE}openssl 安装完成${COLOR_RESET}"
fi
fi
openssl genrsa -out etcd-ca.key 2048
openssl req -x509 -new -nodes -key etcd-ca.key -subj "/CN=$etcd_current_ip" -days 36500 -out etcd-ca.crt
cp etcd-ca.key /etc/etcd/pki/ca.key
cp etcd-ca.crt /etc/etcd/pki/ca.crt
ls -lh /etc/etcd/pki/ca.key
ls -lh /etc/etcd/pki/ca.crt
cat >etcd_ssl.cnf <<EOF
[ req ]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]
EOF
cat etcd_ssl.cnf
local etcd_num=1
echo "IP.$etcd_num = $etcd_current_ip" >>etcd_ssl.cnf
for etcd_ip in "${etcd_ips[@]}"; do
etcd_num=$(($etcd_num + 1))
echo "IP.$etcd_num = $etcd_ip" >>etcd_ssl.cnf
done
cat etcd_ssl.cnf
# 创建 etcd 服务端 CA 证书
openssl genrsa -out etcd_server.key 2048
openssl req -new -key etcd_server.key -config etcd_ssl.cnf -subj "/CN=etcd-server" -out etcd_server.csr
openssl x509 -req -in etcd_server.csr -CA /etc/etcd/pki/ca.crt -CAkey /etc/etcd/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_server.crt
cp etcd_server.crt /etc/etcd/pki/
cp etcd_server.key /etc/etcd/pki/
ls -lh /etc/etcd/pki/etcd_server.crt
ls -lh /etc/etcd/pki/etcd_server.key
# 创建 etcd 客户端 CA 证书
openssl genrsa -out etcd_client.key 2048
openssl req -new -key etcd_client.key -config etcd_ssl.cnf -subj "/CN=etcd-client" -out etcd_client.csr
openssl x509 -req -in etcd_client.csr -CA /etc/etcd/pki/ca.crt -CAkey /etc/etcd/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_client.crt
cp etcd_client.crt /etc/etcd/pki/
cp etcd_client.key /etc/etcd/pki/
ls -lh /etc/etcd/pki/etcd_client.crt
ls -lh /etc/etcd/pki/etcd_client.key
etcd_ips_names_length=${#etcd_ips_names[@]}
etcd_init_name=etcd-1
if [[ $etcd_ips_names_length != 0 ]]; then
etcd_init_name=${etcd_ips_names[0]}
fi
cat >/etc/etcd/etcd.conf <<EOF
# 节点名称,每个节点不同
ETCD_NAME=$etcd_init_name
# 数据目录
ETCD_DATA_DIR=/etc/etcd/data
# etcd 服务端CA证书-crt
ETCD_CERT_FILE=/etc/etcd/pki/etcd_server.crt
# etcd 服务端CA证书-key
ETCD_KEY_FILE=/etc/etcd/pki/etcd_server.key
ETCD_TRUSTED_CA_FILE=/etc/etcd/pki/ca.crt
# 是否启用客户端证书认证
ETCD_CLIENT_CERT_AUTH=true
# 客户端提供的服务监听URL地址
ETCD_LISTEN_CLIENT_URLS=https://$etcd_current_ip:$etcd_client_port_2379
ETCD_ADVERTISE_CLIENT_URLS=https://$etcd_current_ip:$etcd_client_port_2379
# 集群各节点相互认证使用的CA证书-crt
ETCD_PEER_CERT_FILE=/etc/etcd/pki/etcd_server.crt
# 集群各节点相互认证使用的CA证书-key
ETCD_PEER_KEY_FILE=/etc/etcd/pki/etcd_server.key
# CA 根证书
ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/pki/ca.crt
# 为本集群其他节点提供的服务监听URL地址
ETCD_LISTEN_PEER_URLS=https://$etcd_current_ip:$etcd_peer_port_2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://$etcd_current_ip:$etcd_peer_port_2380
# 集群名称
ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
# 集群各节点endpoint列表
ETCD_INITIAL_CLUSTER="$etcd_initial_cluster"
# 初始集群状态
ETCD_INITIAL_CLUSTER_STATE=new
EOF
cat /etc/etcd/etcd.conf
cat >/usr/lib/systemd/system/etcd.service <<EOF
[Unit]
Description=etcd key-value store
Documentation=https://github.com/etcd-io/etcd
After=network.target
[Service]
EnvironmentFile=/etc/etcd/etcd.conf
ExecStart=/usr/local/bin/etcd
Restart=always
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
cat /usr/lib/systemd/system/etcd.service
systemctl daemon-reload
systemctl enable etcd.service
systemctl restart etcd.service
systemctl status etcd.service -l --no-pager
local test_etcd
if ! [[ $etcd_ips ]]; then
test_etcd=true
fi
if [[ $etcd_ips_length == 1 ]]; then
test_etcd=true
fi
if [[ $test_etcd == true ]]; then
etcdctl --cacert=/etc/etcd/pki/ca.crt --cert=/etc/etcd/pki/etcd_client.crt --key=/etc/etcd/pki/etcd_client.key --endpoints=https://"$etcd_current_ip":$etcd_client_port_2379 endpoint health
fi
}
_etcd_binary_join() {
_firewalld_stop
if ! [[ $etcd_current_ip ]]; then
etcd_current_ip=$(hostname -I | awk '{print $1}')
fi
if [[ -f /root/.ssh/id_rsa ]]; then
mv /root/.ssh/id_rsa /root/.ssh/id_rsa.$(date +%Y%m%d%H%M%S)
fi
if [[ -f /root/.ssh/id_rsa.pub ]]; then
mv /root/.ssh/id_rsa.pub /root/.ssh/id_rsa.pub.$(date +%Y%m%d%H%M%S)
fi
ssh-keygen -t rsa -f /root/.ssh/id_rsa -N '' -q
ssh-keyscan -H $etcd_join_ip -P $etcd_join_port >>/root/.ssh/known_hosts
if [[ $etcd_join_password ]]; then
if ! command -v 'sshpass' &>/dev/null; then
if [[ $package_type == 'yum' ]]; then
sudo yum install -y sshpass
else
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y sshpass
fi
fi
sshpass -p $etcd_join_password scp -P $etcd_join_port /root/.ssh/id_rsa.pub root@$etcd_join_ip:/root/.ssh/authorized_keys
else
scp -P $etcd_join_port /root/.ssh/id_rsa.pub root@$etcd_join_ip:/root/.ssh/authorized_keys
fi
mkdir -p /etc/etcd/pki
scp -P $etcd_join_port root@$etcd_join_ip:/usr/local/bin/etcd /usr/local/bin/
scp -P $etcd_join_port root@$etcd_join_ip:/usr/local/bin/etcdctl /usr/local/bin/
scp -P $etcd_join_port root@$etcd_join_ip:/usr/local/bin/etcdutl /usr/local/bin/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/pki/ca.key /etc/etcd/pki/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/pki/ca.crt /etc/etcd/pki/
scp -P $etcd_join_port root@$etcd_join_ip:/usr/lib/systemd/system/etcd.service /usr/lib/systemd/system/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/pki/etcd_server.crt /etc/etcd/pki/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/pki/etcd_server.key /etc/etcd/pki/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/pki/etcd_client.crt /etc/etcd/pki/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/pki/etcd_client.key /etc/etcd/pki/
scp -P $etcd_join_port root@$etcd_join_ip:/etc/etcd/etcd.conf /etc/etcd/
source /etc/etcd/etcd.conf
echo $ETCD_INITIAL_CLUSTER
etcd_from_name=$ETCD_NAME
echo $etcd_from_name
etcd_current_ip=$(hostname -I | awk '{print $1}')
echo $etcd_current_ip
IFS=',' read -ra etcd_nodes <<<"$ETCD_INITIAL_CLUSTER"
for etcd_node in "${etcd_nodes[@]}"; do
echo $etcd_node
if [[ $etcd_node =~ $etcd_current_ip ]]; then
node_name=$(echo $etcd_node | awk -F'=' '{print $1}')
break
fi
done
echo $node_name
sudo sed -i "s#ETCD_NAME=$etcd_from_name#ETCD_NAME=$node_name#g" /etc/etcd/etcd.conf
sudo sed -i "s#ETCD_LISTEN_CLIENT_URLS=https://$etcd_join_ip:$etcd_client_port_2379#ETCD_LISTEN_CLIENT_URLS=https://$etcd_current_ip:$etcd_client_port_2379#g" /etc/etcd/etcd.conf
sudo sed -i "s#ETCD_ADVERTISE_CLIENT_URLS=https://$etcd_join_ip:$etcd_client_port_2379#ETCD_ADVERTISE_CLIENT_URLS=https://$etcd_current_ip:$etcd_client_port_2379#g" /etc/etcd/etcd.conf
sudo sed -i "s#ETCD_LISTEN_PEER_URLS=https://$etcd_join_ip:$etcd_peer_port_2380#ETCD_LISTEN_PEER_URLS=https://$etcd_current_ip:$etcd_peer_port_2380#g" /etc/etcd/etcd.conf
sudo sed -i "s#ETCD_INITIAL_ADVERTISE_PEER_URLS=https://$etcd_join_ip:$etcd_peer_port_2380#ETCD_INITIAL_ADVERTISE_PEER_URLS=https://$etcd_current_ip:$etcd_peer_port_2380#g" /etc/etcd/etcd.conf
/usr/local/bin/etcd --version
/usr/local/bin/etcdctl version
/usr/local/bin/etcdutl version
systemctl daemon-reload
systemctl enable etcd.service
systemctl restart etcd.service
systemctl status etcd.service -l --no-pager
}
while [[ $# -gt 0 ]]; do
case "$1" in
config=* | -config=* | --config=*)
config="${1#*=}"
echo -e "${COLOR_BLUE}启用了配置文件 ${COLOR_GREEN}$config${COLOR_RESET}"
source $config
;;
standalone | -standalone | --standalone)
standalone=true
;;
cluster | -cluster | --cluster)
cluster=true
;;
node | -node | --node)
node=true
;;
dpkg-lock-timeout=* | -dpkg-lock-timeout=* | --dpkg-lock-timeout=*)
dpkg_lock_timeout="${1#*=}"
;;
firewalld-stop | -firewalld-stop | --firewalld-stop)
firewalld_stop=true
;;
selinux-disabled | -selinux-disabled | --selinux-disabled)
selinux_disabled=true
;;
bash-completion | -bash-completion | --bash-completion)
bash_completion=true
;;
kubernetes-repo | -kubernetes-repo | --kubernetes-repo)
kubernetes_repo=true
;;
kubernetes-repo-type=* | -kubernetes-repo-type=* | --kubernetes-repo-type=*)
kubernetes_repo_type="${1#*=}"
case "$kubernetes_repo_type" in
aliyun)
kubernetes_baseurl=${kubernetes_mirrors[0]}
;;
tsinghua)
kubernetes_baseurl=${kubernetes_mirrors[1]}
;;
kubernetes)
kubernetes_baseurl=${kubernetes_mirrors[-1]}
;;
*)
echo -e "${COLOR_BLUE}使用自定义 Kubernetes 仓库地址 ${COLOR_GREEN}$kubernetes_repo_type${COLOR_RESET}"
kubernetes_baseurl=$kubernetes_repo_type
;;
esac
;;
kubernetes-images=* | -kubernetes-images=* | --kubernetes-images=*)
kubernetes_images="${1#*=}"
case "$kubernetes_images" in
aliyun)
kubernetes_images=${kubernetes_images_mirrors[0]}
;;
xuxiaoweicomcn)
kubernetes_images=${kubernetes_images_mirrors[1]}
;;
kubernetes)
kubernetes_images=${kubernetes_images_mirrors[-1]}
;;
*)
echo -e "${COLOR_RED}不支持自定义 Kubernetes 镜像仓库: ${COLOR_GREEN}$kubernetes_images${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看 Kubernetes 镜像仓库配置 kubernetes-images: ${COLOR_GREEN}${DOCS_CONFIG_LINK}#kubernetes-images${COLOR_RESET}"
exit 1
;;
esac
;;
swap-off | -swap-off | --swap-off)
swap_off=true
;;
curl | -curl | --curl)
curl=true
;;
ca-certificates | -ca-certificates | --ca-certificates)
ca_certificates=true
;;
kubernetes-install | -kubernetes-install | --kubernetes-install)
kubernetes_install=true
;;
kubernetes-images-pull | -kubernetes-images-pull | --kubernetes-images-pull)
kubernetes_images_pull=true
;;
kubernetes-config | -kubernetes-config | --kubernetes-config)
kubernetes_config=true
;;
kubernetes-init | -kubernetes-init | --kubernetes-init)
kubernetes_init=true
;;
kubernetes-init-congrats | -kubernetes-init-congrats | --kubernetes-init-congrats)
kubernetes_init_congrats=true
;;
kubernetes-init-node-name=* | -kubernetes-init-node-name=* | --kubernetes-init-node-name=*)
kubernetes_init_node_name="${1#*=}"
;;
control-plane-endpoint=* | -control-plane-endpoint=* | --control-plane-endpoint=*)
# 关于 apiserver-advertise-address 和 ControlPlaneEndpoint 的注意事项
# https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#considerations-about-apiserver-advertise-address-and-controlplaneendpoint
# https://kubernetes.xuxiaowei.com.cn/zh-cn/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#considerations-about-apiserver-advertise-address-and-controlplaneendpoint
control_plane_endpoint="${1#*=}"
;;
service-cidr=* | -service-cidr=* | --service-cidr=*)
# kubeadm init
# --service-cidr string 默认值:"10.96.0.0/12"
# https://kubernetes.io/zh-cn/docs/reference/setup-tools/kubeadm/kubeadm-init/
# https://kubernetes.xuxiaowei.com.cn/zh-cn/docs/reference/setup-tools/kubeadm/kubeadm-init/
service_cidr="${1#*=}"
;;
pod-network-cidr=* | -pod-network-cidr=* | --pod-network-cidr=*)
pod_network_cidr="${1#*=}"
;;
print-join-command | -print-join-command | --print-join-command)
print_join_command=true
;;
kubernetes-taint | -kubernetes-taint | --kubernetes-taint)
kubernetes_taint=true
;;
kubernetes-version=* | -kubernetes-version=* | --kubernetes-version=*)
kubernetes_version="${1#*=}"
_k8s_support_kernel
;;
kubernetes-version-suffix=* | -kubernetes-version-suffix=* | --kubernetes-version-suffix=*)
kubernetes_version_suffix="${1#*=}"
;;
enable-shell-autocompletion | -enable-shell-autocompletion | --enable-shell-autocompletion)
enable_shell_autocompletion=true
;;
docker-repo | -docker-repo | --docker-repo)
docker_repo=true
;;
docker-repo-type=* | -docker-repo-type=* | --docker-repo-type=*)
docker_repo_type="${1#*=}"
case "$docker_repo_type" in
aliyun)
docker_baseurl=${docker_mirrors[0]}
;;
tencent)
docker_baseurl=${docker_mirrors[1]}
;;
docker)
docker_baseurl=${docker_mirrors[-1]}
;;
*)
echo -e "${COLOR_BLUE}使用自定义 Docker 仓库地址: ${COLOR_GREEN}$docker_repo_type${COLOR_RESET}"
docker_baseurl=$docker_repo_type
;;
esac
;;
container-selinux-rpm=* | -container-selinux-rpm=* | --container-selinux-rpm=*)
container_selinux_rpm="${1#*=}"
;;
containerd-install | -containerd-install | --containerd-install)
containerd_install=true
;;
pause-image=* | -pause-image=* | --pause-image=*)
pause_image="${1#*=}"
;;
containerd-config | -containerd-config | --containerd-config)
containerd_config=true
;;
containerd-root=* | -containerd-root=* | --containerd-root=*)
containerd_root="${1#*=}"
;;
containerd-state=* | -containerd-state=* | --containerd-state=*)
containerd_state="${1#*=}"
;;
docker-install | -docker-install | --docker-install)
docker_install=true
;;
interface-name=* | -interface-name=* | --interface-name=*)
interface_name="${1#*=}"
;;
calico-install | -calico-install | --calico-install)
calico_install=true
;;
calico-url=* | -calico-url=* | --calico-url=*)
calico_url="${1#*=}"
;;
calico-mirror=* | -calico-mirror=* | --calico-mirror=*)
calico_mirror="${1#*=}"
;;
calico-version=* | -calico-version=* | --calico-version=*)
calico_version="${1#*=}"
;;
calico-node-image=* | -calico-node-image=* | --calico-node-image=*)
calico_node_image="${1#*=}"
;;
calico-cni-image=* | -calico-cni-image=* | --calico-cni-image=*)
calico_cni_image="${1#*=}"
;;
calico-kube-controllers-image=* | -calico-kube-controllers-image=* | --calico-kube-controllers-image=*)
calico_kube_controllers_image="${1#*=}"
;;
ingress-nginx-install | -ingress-nginx-install | --ingress-nginx-install)
ingress_nginx_install=true
;;
ingress-nginx-host-network | -ingress-nginx-host-network | --ingress-nginx-host-network)
ingress_nginx_host_network=true
;;
ingress-nginx-url=* | -ingress-nginx-url=* | --ingress-nginx-url=*)
ingress_nginx_url="${1#*=}"
;;
ingress-nginx-mirror=* | -ingress-nginx-mirror=* | --ingress-nginx-mirror=*)
ingress_nginx_mirror="${1#*=}"
;;
ingress-nginx-version=* | -ingress-nginx-version=* | --ingress-nginx-version=*)
ingress_nginx_version="${1#*=}"
;;
ingress-nginx-controller-image=* | -ingress-nginx-controller-image=* | --ingress-nginx-controller-image=*)
ingress_nginx_controller_image="${1#*=}"
;;
ingress-nginx-kube-webhook-certgen-image=* | -ingress-nginx-kube-webhook-certgen-image=* | --ingress-nginx-kube-webhook-certgen-image=*)
ingress_nginx_kube_webhook_certgen_image="${1#*=}"
;;
ingress-nginx-allow-snippet-annotations | -ingress-nginx-allow-snippet-annotations | --ingress-nginx-allow-snippet-annotations)
ingress_nginx_allow_snippet_annotations=true
;;
metrics-server-install | -metrics-server-install | --metrics-server-install)
metrics_server_install=true
;;
metrics-server-url=* | -metrics-server-url=* | --metrics-server-url=*)
metrics_server_url="${1#*=}"
;;
metrics-server-version=* | -metrics-server-version=* | --metrics-server-version=*)
metrics_server_version="${1#*=}"
;;
metrics-server-mirror=* | -metrics-server-mirror=* | --metrics-server-mirror=*)
metrics_server_mirror="${1#*=}"
;;
metrics-server-image=* | -metrics-server-image=* | --metrics-server-image=*)
metrics_server_image="${1#*=}"
;;
metrics-server-secure-tls | -metrics-server-secure-tls | --metrics-server-secure-tls)
metrics_server_secure_tls=true
;;
helm-install | -helm-install | --helm-install)
helm_install=true
;;
helm-version=* | -helm-version=* | --helm-version=*)
helm_version="${1#*=}"
;;
helm-url=* | -helm-url=* | --helm-url=*)
helm_url="${1#*=}"
;;
helm-repo-type=* | -helm-repo-type=* | --helm-repo-type=*)
helm_repo_type="${1#*=}"
case "$helm_repo_type" in
"" | huawei | helm) ;;
*)
echo -e "${COLOR_RED}helm-repo-type 参数值: ${COLOR_GREEN}$helm_repo_type${COLOR_RED} 无效,合法值: 空、huawei、helm,或者使用 helm-url 自定义 helm 下载地址,退出程序${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看 helm 仓库配置 helm-repo-type: ${COLOR_GREEN}${DOCS_CONFIG_LINK}#helm-repo-type${COLOR_RESET}"
exit 1
;;
esac
;;
helm-install-kubernetes-dashboard | -helm-install-kubernetes-dashboard | --helm-install-kubernetes-dashboard)
helm_install_kubernetes_dashboard=true
;;
kubernetes-dashboard-chart=* | -kubernetes-dashboard-chart=* | --kubernetes-dashboard-chart=*)
kubernetes_dashboard_chart="${1#*=}"
;;
kubernetes-dashboard-version=* | -kubernetes-dashboard-version=* | --kubernetes-dashboard-version=*)
kubernetes_dashboard_version="${1#*=}"
;;
kubernetes-dashboard-auth-image=* | -kubernetes-dashboard-auth-image=* | --kubernetes-dashboard-auth-image=*)
kubernetes_dashboard_auth_image="${1#*=}"
;;
kubernetes-dashboard-api-image=* | -kubernetes-dashboard-api-image=* | --kubernetes-dashboard-api-image=*)
kubernetes_dashboard_api_image="${1#*=}"
;;
kubernetes-dashboard-web-image=* | -kubernetes-dashboard-web-image=* | --kubernetes-dashboard-web-image=*)
kubernetes_dashboard_web_image="${1#*=}"
;;
kubernetes-dashboard-metrics-scraper-image=* | -kubernetes-dashboard-metrics-scraper-image=* | --kubernetes-dashboard-metrics-scraper-image=*)
kubernetes_dashboard_metrics_scraper_image="${1#*=}"
;;
kubernetes-dashboard-kong-image=* | -kubernetes-dashboard-kong-image=* | --kubernetes-dashboard-kong-image=*)
kubernetes_dashboard_kong_image="${1#*=}"
;;
kubernetes-dashboard-ingress-enabled=* | -kubernetes-dashboard-ingress-enabled=* | --kubernetes-dashboard-ingress-enabled=*)
kubernetes_dashboard_ingress_enabled="${1#*=}"
if [[ $kubernetes_dashboard_ingress_enabled != 'true' && $kubernetes_dashboard_ingress_enabled != 'false' ]]; then
echo -e "${COLOR_RED}无效参数: kubernetes-dashboard-ingress-enabled=$kubernetes_dashboard_ingress_enabled,合法值:true/false,退出程序${COLOR_RESET}"
fi
;;
kubernetes-dashboard-ingress-host=* | -kubernetes-dashboard-ingress-host=* | --kubernetes-dashboard-ingress-host=*)
kubernetes_dashboard_ingress_host="${1#*=}"
;;
etcd-binary-install | -etcd-binary-install | --etcd-binary-install)
etcd_binary_install=true
;;
etcd-ips=* | -etcd-ips=* | --etcd-ips=*)
etcd_ips+=("${1#*=}")
;;
etcd-client-port-2379=* | -etcd-client-port-2379=* | --etcd-client-port-2379=*)
etcd_client_port_2379="${1#*=}"
;;
etcd-peer-port-2380=* | -etcd-peer-port-2380=* | --etcd-peer-port-2380=*)
etcd_peer_port_2380="${1#*=}"
;;
etcd-url=* | -etcd-url=* | --etcd-url=*)
etcd_url="${1#*=}"
;;
etcd-version=* | -etcd-version=* | --etcd-version=*)
etcd_version="${1#*=}"
;;
etcd-current-ip=* | -etcd-current-ip=* | --etcd-current-ip=*)
etcd_current_ip="${1#*=}"
;;
etcd-binary-join | -etcd-binary-join | --etcd-binary-join)
etcd_binary_join=true
;;
etcd-join-ip=* | -etcd-join-ip=* | --etcd-join-ip=*)
etcd_join_ip="${1#*=}"
;;
etcd-join-port=* | -etcd-join-port=* | --etcd-join-port=*)
etcd_join_port="${1#*=}"
;;
etcd-cafile=* | -etcd-cafile=* | --etcd-cafile=*)
etcd_cafile="${1#*=}"
;;
etcd-certfile=* | -etcd-certfile=* | --etcd-certfile=*)
etcd_certfile="${1#*=}"
;;
etcd-keyfile=* | -etcd-keyfile=* | --etcd-keyfile=*)
etcd_keyfile="${1#*=}"
;;
*)
echo -e "${COLOR_RED}无效参数: $1,退出程序${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看参数配置: ${COLOR_GREEN}$DOCS_CONFIG_LINK${COLOR_RESET}"
exit 1
;;
esac
shift
done
if ! command -v 'sudo' &>/dev/null; then
if [[ $package_type == 'apt' ]]; then
echo -e "${COLOR_BLUE}sudo 未安装,正在安装...${COLOR_RESET}"
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout update
apt-get -o Dpkg::Lock::Timeout=$dpkg_lock_timeout install -y sudo
echo -e "${COLOR_BLUE}sudo 安装完成${COLOR_RESET}"
fi
fi
_node() {
_swap_off
_curl
_ca_certificates
_firewalld_stop
_selinux_disabled
_bash_completion
_docker_repo
_containerd_install
_containerd_config
_kubernetes_repo
_kubernetes_install
_kubernetes_images_pull
_kubernetes_config
}
# 三者互斥
count=0
if [[ $standalone == true ]]; then
count=$(expr $count + 1)
fi
if [[ $cluster == true ]]; then
count=$(expr $count + 1)
fi
if [[ $node == true ]]; then
count=$(expr $count + 1)
fi
if [[ $count -gt 1 ]]; then
echo ''
echo ''
echo ''
echo -e "${COLOR_RED}${EMOJI_FAILURE}${EMOJI_FAILURE}${EMOJI_FAILURE}${COLOR_RESET}"
echo -e "${COLOR_RED}参数 standalone、cluster、node 三者互斥${COLOR_RESET}"
echo -e "${COLOR_RED}请阅读文档,查看配置: ${COLOR_GREEN}$DOCS_CONFIG_LINK${COLOR_RESET}"
echo ''
echo ''
echo ''
exit 1
fi
if [[ $standalone == true ]]; then
# 单机模式
if ! [[ $kubernetes_init_node_name ]]; then
kubernetes_init_node_name=k8s-1
fi
_node
_kubernetes_init
_helm_install
_calico_install
_kubernetes_taint
_ingress_nginx_install
_ingress_nginx_host_network
_metrics_server_install
_enable_shell_autocompletion
_print_join_command
_kubernetes_init_congrats
elif [[ $cluster == true ]]; then
# 集群模式
if ! [[ $kubernetes_init_node_name ]]; then
kubernetes_init_node_name=k8s-1
fi
_node
_kubernetes_init
_helm_install
_calico_install
_ingress_nginx_install
_ingress_nginx_host_network
_metrics_server_install
_enable_shell_autocompletion
_print_join_command
_kubernetes_init_congrats
elif [[ $node == true ]]; then
# 工作节点准备
_node
echo
echo
echo
echo -e "${COLOR_BLUE}${EMOJI_CONGRATS}${EMOJI_CONGRATS}${EMOJI_CONGRATS}${COLOR_RESET}"
echo -e "${COLOR_BLUE}Kubernetes 节点已配置完成${COLOR_RESET}"
echo
echo -e "${COLOR_BLUE}请选择下列方式之一:${COLOR_RESET}"
echo
echo -e "${COLOR_BLUE}1. 初始化为控制节点(控制平面)${COLOR_RESET}"
echo -e "${COLOR_BLUE}2. 作为工作节点加入集群${COLOR_RESET}"
echo
echo
echo
else
if [[ $swap_off == true ]]; then
_swap_off
fi
if [[ $curl == true ]]; then
_curl
fi
if [[ $ca_certificates == true ]]; then
_ca_certificates
fi
if [[ $firewalld_stop == true ]]; then
_firewalld_stop
fi
if [[ $selinux_disabled == true ]]; then
_selinux_disabled
fi
if [[ $bash_completion == true ]]; then
_bash_completion
fi
if [[ $docker_repo == true ]]; then
_docker_repo
fi
if [[ $docker_install == true ]]; then
_docker_install
fi
if [[ $containerd_install == true ]]; then
_containerd_install
fi
if [[ $containerd_config == true ]]; then
_containerd_config
fi
if [[ $kubernetes_repo == true ]]; then
_kubernetes_repo
fi
if [[ $kubernetes_install == true ]]; then
_kubernetes_install
fi
if [[ $kubernetes_images_pull == true ]]; then
_kubernetes_images_pull
fi
if [[ $kubernetes_config == true ]]; then
_kubernetes_config
fi
if [[ $kubernetes_init == true ]]; then
_kubernetes_init
fi
if [[ $helm_install == true ]]; then
_helm_install
fi
if [[ $calico_install == true ]]; then
_calico_install
fi
if [[ $kubernetes_taint == true ]]; then
_kubernetes_taint
fi
if [[ $enable_shell_autocompletion == true ]]; then
_enable_shell_autocompletion
fi
if [[ $ingress_nginx_install == true ]]; then
_ingress_nginx_install
fi
if [[ $ingress_nginx_host_network == true ]]; then
_ingress_nginx_host_network
fi
if [[ $ingress_nginx_allow_snippet_annotations == true ]]; then
_ingress_nginx_allow_snippet_annotations
fi
if [[ $metrics_server_install == true ]]; then
_metrics_server_install
fi
if [[ $print_join_command == true ]]; then
_print_join_command
fi
if [[ $kubernetes_init_congrats == true ]]; then
_kubernetes_init_congrats
fi
if [[ $helm_install_kubernetes_dashboard == true ]]; then
_helm_install_kubernetes_dashboard
fi
if [[ $etcd_binary_install == true ]]; then
_etcd_binary_install
fi
if [[ $etcd_binary_join == true ]]; then
_etcd_binary_join
fi
fi