参考文档

https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

安装要求

  • 至少 2CPU 和 2GB 的内存
  • 所有机器的网络彼此均能相互连接
  • 不可以有重复的主机名、MAC 地址或 product_uuid
    • 使用命令 ip link 或 ifconfig -a 来获取网络接口的 MAC 地址
    • 使用 sudo cat /sys/class/dmi/id/product_uuid 命令对 product_uuid 校验
  • 禁用交换分区

脚本自动配置安装

  1. #!/usr/bin/env sh
  2. # author: acdiost
  3. # desc: 安装 kubernetes 脚本,按需修改
  4. function initial(){
  5. modprobe br_netfilter
  6. if [[ $? -ne 0 ]];then
  7. echo '未找到 br_netfilter 模块,退出安装'
  8. exit
  9. fi
  10. timedatectl set-timezone Asia/Shanghai
  11. yum install chrony -y
  12. systemctl start chronyd && systemctl enable chronyd
  13. chronyc sources
  14. systemctl stop firewalld && systemctl disable firewalld
  15. swapoff -a
  16. sed -ri 's/.*swap.*/#&/' /etc/fstab
  17. HARBOR_IP=""
  18. default_nic=`ip route | grep '^default' | awk '{print $5}'`
  19. default_ip=`ip addr show ${default_nic} | grep inet | grep -v "inet6" | grep brd | awk '{print $2}' | cut -f 1 -d /`
  20. cat <<EOF | tee >> /etc/hosts
  21. # 若有私有仓库
  22. # $HARBOR_IP docker.io gcr.io k8s.gcr.io quay.io registry-1.docker.io
  23. $default_ip `hostname`
  24. EOF
  25. setenforce 0
  26. sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
  27. }
  28. function update_kernel(){
  29. kernelVersion=$(uname -r | cut -b 1-4)
  30. if [ $(echo "${kernelVersion} > 4.19" | bc) -eq 1 ];then
  31. echo '内核大于 4.19 不进行升级'
  32. return 0
  33. fi
  34. rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
  35. yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
  36. yum --enablerepo=elrepo-kernel install -y kernel-ml
  37. kernelId=$(awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg | grep "5.12" | grep -vi rescue | awk '{print $1}')
  38. grub2-set-default ${kernelId}
  39. echo '5 秒后将重启系统,注意保存资料,完成后再执行该脚本'
  40. sleep 5
  41. reboot
  42. }
  43. function install_ipvs(){
  44. yum install socat ipvsadm ipset -y
  45. result=$(echo "$(uname -r | cut -b 1-4) > 4.19" | bc)
  46. if [ ${result} -eq 1 ];then
  47. echo '内核版本大于 4.19'
  48. cat <<EOF | tee /etc/sysconfig/modules/ipvs.modules
  49. #!/bin/bash
  50. modprobe -- ip_vs
  51. modprobe -- ip_vs_rr
  52. modprobe -- ip_vs_wrr
  53. modprobe -- ip_vs_sh
  54. modprobe -- nf_conntrack
  55. EOF
  56. else
  57. echo '内核版本小于 4.19'
  58. cat <<EOF | tee /etc/sysconfig/modules/ipvs.modules
  59. #!/bin/bash
  60. modprobe -- ip_vs
  61. modprobe -- ip_vs_rr
  62. modprobe -- ip_vs_wrr
  63. modprobe -- ip_vs_sh
  64. # 4.19内核将 nf_conntrack_ipv4 更名为 nf_conntrack
  65. modprobe -- nf_conntrack_ipv4
  66. EOF
  67. fi
  68. chmod 755 /etc/sysconfig/modules/ipvs.modules
  69. bash /etc/sysconfig/modules/ipvs.modules
  70. }
  71. function install_containerd(){
  72. curl -o /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
  73. cat <<EOF | tee /etc/modules-load.d/containerd.conf
  74. overlay
  75. br_netfilter
  76. EOF
  77. modprobe overlay
  78. modprobe br_netfilter
  79. cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf
  80. net.bridge.bridge-nf-call-iptables = 1
  81. net.ipv4.ip_forward = 1
  82. net.bridge.bridge-nf-call-ip6tables = 1
  83. EOF
  84. sysctl --system
  85. yum makecache fast
  86. yum install containerd.io -y
  87. mkdir -p /etc/containerd
  88. containerd config default | tee /etc/containerd/config.toml
  89. sed -i '/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' /etc/containerd/config.toml
  90. systemctl daemon-reload
  91. systemctl enable containerd
  92. systemctl restart containerd
  93. }
  94. function install_k8s(){
  95. cat <<EOF | tee /etc/modules-load.d/k8s.conf
  96. br_netfilter
  97. EOF
  98. cat <<EOF | tee /etc/sysctl.d/k8s.conf
  99. net.bridge.bridge-nf-call-ip6tables = 1
  100. net.bridge.bridge-nf-call-iptables = 1
  101. vm.swappiness = 0
  102. EOF
  103. sysctl --system
  104. cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
  105. [kubernetes]
  106. name=Kubernetes
  107. baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
  108. enabled=1
  109. gpgcheck=1
  110. repo_gpgcheck=1
  111. gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
  112. exclude=kubelet kubeadm kubectl
  113. EOF
  114. yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
  115. systemctl enable --now kubelet
  116. }
  117. function kubeadm_init(){
  118. echo '镜像下载中...'
  119. kubeadm config images pull
  120. crictl config runtime-endpoint /run/containerd/containerd.sock
  121. kubeadm init --pod-network-cidr=192.168.0.0/16
  122. mkdir -p $HOME/.kube
  123. cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  124. chown $(id -u):$(id -g) $HOME/.kube/config
  125. echo 'export KUBECONFIG=/etc/kubernetes/admin.conf'
  126. echo '执行 crictl 命令'
  127. echo 'crictl config runtime-endpoint /run/containerd/containerd.sock'
  128. }
  129. function clean(){
  130. # 初始化清理
  131. kubeadm reset -f
  132. ipvsadm -C
  133. # docker rmi $(docker images -q)
  134. # yum list installed | grep kube | awk '{print $1}' | xargs yum -y remove
  135. # yum list installed | grep docker | awk '{print $1}' | xargs yum -y remove
  136. }
  137. function auto_completion(){
  138. yum install bash-completion -y
  139. echo 'source <(kubectl completion bash)' >> ~/.bashrc
  140. }
  141. function main(){
  142. initial
  143. # update_kernel
  144. install_ipvs
  145. install_containerd
  146. install_k8s
  147. auto_completion
  148. echo '初始化主节点取消注释脚本的内容'
  149. # kubeadm_init
  150. echo -e '若未初始化网络则可执行如下命令\n'
  151. echo '大于 50 节点执行:kubectl create -f https://docs.projectcalico.org/manifests/calico-typha.yaml'
  152. echo '少于 50 节点执行:kubectl create -f https://docs.projectcalico.org/manifests/calico.yaml'
  153. }
  154. main

准备工作

确保 br_netfilter 模块被加载

  • 可以通过运行 lsmod | grep br_netfilter 来完成。若要显式加载该模块,可执行 sudo modprobe br_netfilter

时间同步

yum install chrony -y
systemctl start chronyd && systemctl enable chronyd
chronyc sources

配置 sysctl

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness = 0
EOF
modprobe br_netfilter
sudo sysctl --system

配置 hosts

添加 hostname 和 IP

cat <<EOF | sudo tee >> /etc/hosts
# 若有私有仓库
# $HARBOR_IP docker.io gcr.io k8s.gcr.io quay.io registry-1.docker.io
`hostname -i` `hostname`
`hostname -I` `hostname`
EOF

检查所需端口

关闭防火墙

systemctl stop firewalld && systemctl disable firewalld

关闭 swap 分区

swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab

关闭 selinux

# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

IPVS

cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules
bash /etc/sysconfig/modules/ipvs.modules

yum install ipvsadm ipset -y

安装 runtime

https://kubernetes.io/docs/setup/production-environment/container-runtimes/

Docker

wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
sudo yum makecache fast
sudo yum install -y docker-ce-19.03.15 # -version

mkdir /etc/docker

cat <<EOF | tee /etc/docker/daemon.json
{
  "insecure-registries": ["harbor.address", "gcr.io", "docker.io", "k8s.gcr.io", "registry-1.docker.io"],
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

systemctl daemon-reload
systemctl enable docker
systemctl start docker

containerd

cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sudo sysctl --system

yum install containerd.io -y
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

sed -i '/containerd.runtimes.runc.options/a\ \ \ \ \ \ \ \ \ \ \ \ SystemdCgroup = true' /etc/containerd/config.toml
# sed -i "s#k8s.gcr.io#registry.cn-hangzhou.aliyuncs.com/google_containers#g"  /etc/containerd/config.toml
# sed -i "s#https://registry-1.docker.io#https://registry.cn-hangzhou.aliyuncs.com#g"  /etc/containerd/config.toml

systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd
# 初始化前须设置容器运行时
crictl config runtime-endpoint /run/containerd/containerd.sock

containerd 导出镜像

kubeadm config images list

ctr images pull k8s.gcr.io/coredns/coredns:v1.8.0
ctr images pull k8s.gcr.io/etcd:3.4.13-0
ctr images pull k8s.gcr.io/kube-controller-manager:v1.21.1
ctr images pull k8s.gcr.io/kube-proxy:v1.21.1
ctr images pull k8s.gcr.io/kube-apiserver:v1.21.1
ctr images pull k8s.gcr.io/kube-scheduler:v1.21.1
ctr images pull k8s.gcr.io/pause:3.4.1
ctr images pull k8s.gcr.io/pause:3.2

ctr images pull docker.io/calico/cni:v3.19.1
ctr images pull docker.io/calico/kube-controllers:v3.19.1
ctr images pull docker.io/calico/node:v3.19.1
ctr images pull docker.io/calico/pod2daemon-flexvol:v3.19.1

ctr images pull docker.io/kubernetesui/dashboard:v2.2.0
ctr images pull docker.io/kubernetesui/metrics-scraper:v1.0.6

# ctr image export <output-filename> <image-name>
ctr images ls | grep -v REF | awk '{print $1}' | tr '\n' ' ' | xargs ctr images export k8sImage.tar

ctr -n=k8s.io images import k8sImage.tar

问题:
节点初始化完成后,执行 crictl ps 命令遇到该错

FATA[0010] failed to connect: failed to connect: context deadline exceeded

执行: crictl config runtime-endpoint /run/containerd/containerd.sock

cri-o

curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/devel:kubic:libcontainers:stable.repo
curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
yum install cri-o

安装 kubeadm、kubelet 和 kubectl

清华镜像

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=kubernetes baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-\$basearch enabled=1 gpgcheck=0 EOF

华为镜像

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://repo.huaweicloud.com/kubernetes/yum/repos/kubernetes-el7-\$basearch enabled=1 gpgcheck=1 repo_gpgcheck=0 gpgkey=https://repo.huaweicloud.com/kubernetes/yum/doc/yum-key.gpg https://repo.huaweicloud.com/kubernetes/yum/doc/rpm-package-key.gpg EOF

查看可用版本

yum list available —showduplicates —disablerepo=”*” —enablerepo=kubernetes

kubeVersion=1.19.12

sudo yum install -y kubelet-${kubeVersion} kubeadm-${kubeVersion} kubectl-${kubeVersion} —disableexcludes=kubernetes

sudo yum install -y kubelet kubeadm kubectl —disableexcludes=kubernetes # —nogpgcheck

sudo systemctl enable —now kubelet


<a name="jBv2L"></a>
### 初始化集群
```bash
# 初始化之前准备好镜像
kubeadm config images pull

# 可以通过如下命令导出默认的初始化配置,然后根据我们自己的需求修改配置
kubeadm config print init-defaults > kubeadm.yaml
# 使用上面的配置文件进行初始化
kubeadm init --config=kubeadm.yaml


kubeadm init \
--image-repository registry.aliyuncs.com/google_containers #\
# --apiserver-advertise-address=1.2.3.4 \
# --service-cidr=10.96.0.0/12 \
# --kubernetes-version v1.20.0 \
# --pod-network-cidr=10.244.0.0/16 # 不推荐 flannel 网络

# 初始化完成后
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# root 用户
export KUBECONFIG=/etc/kubernetes/admin.conf

# 初始化失败可执行如下命令
kubeadm reset -f
# docker rmi $(docker images -q)
# yum list installed | grep kube | awk '{print $1}' | xargs yum -y remove
# yum list installed | grep docker | awk '{print $1}' | xargs yum -y remove

遇到的错误

[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory “/etc/kubernetes/manifests”. This can take up to 4m0s [kubelet-check] Initial timeout of 40s passed.

image.png
移除初始化参数 --apiserver-advertise-address 或者将其改为内网 IP
1.21.0 的高版本问题,用 containerd 作为运行时可正常初始化

The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz‘ failed with error: Get “http://localhost:10248/healthz“: dial tcp 127.0.0.1:10248: connect: connection refused.

"exec-opts": ["native.cgroupdriver=systemd"], 移除 docker 的此项配置,1.19 以下版本正常
或者

# 创建文件夹
mkdir /etc/systemd/system/kubelet.service.d
# 创建文件
vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# 添加如下内容
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --fail-swap-on=false"
# 重置
kubeadm reset -f

节点加入集群

kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

# 主节点运行
kubeadm token create --print-join-command
# echo "kubeadm join $(hostname -i):6443 --discovery-token $(kubeadm token list | grep -v TTL | awk '{print $1}') --discovery-token-ca-cert-hash sha256:$(openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //')"

单节点执行如下命令

kubectl taint nodes --all node-role.kubernetes.io/master-

配置 flannel 网络

不再推荐

docker pull quay.io/coreos/flannel:version
# https://github.com/flannel-io/flannel/blob/master/Documentation/kube-flannel.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

配置 Calico网络

curl https://docs.projectcalico.org/manifests/calico.yaml -O
# 超过 50 节点:curl https://docs.projectcalico.org/manifests/calico-typha.yaml -o calico.yaml
kubectl apply -f calico.yaml

修改 kube-proxy 实现 ipvsadm

yum install ipvsadm -y

# 修改 kube-proxy 
kubectl edit configmap -n kube-system kube-proxy

# !!! 找到 mode: "" 修改为 mode: "ipvs"

# 修改后删除正在运行的 kube-proxy
kubectl delete pod -n kube-system -l k8s-app=kube-proxy

# 检查
ipvsadm -l -n

image.png
image.png

测试集群

kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pod,svc

安装面板

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml

# 外部访问
kubectl get pods -n kubernetes-dashboard
kubectl patch svc kubernetes-dashboard -p '{"spec":{"type":"NodePort"}}' -n kubernetes-dashboard
kubectl get svc -n kubernetes-dashboard

# 访问 https://ip:port

# 创建 token
kubectl create serviceaccount dashboard -n kubernetes-dashboard
kubectl create rolebinding def-ns-admin --clusterrole=admin --serviceaccount=default:def-ns-admin
kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard

# 令牌
kubectl -n kubernetes-dashboard describe secret `kubectl describe sa dashboard -n kubernetes-dashboard | grep Tokens | awk '{print $2}'`

常用命令

kubectl get nodes
# 生成 token
kubeadm token list
kubeadm token create
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'

# 删除节点
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
kubeadm reset
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm -C
kubectl delete node <node name>

# 证书过期查询
kubeadm certs check-expiration

# 证书续期
kubeadm certs renew all

自动补全

yum install bash-completion -y

echo 'source <(kubectl completion bash)' >> ~/.bashrc
source <(kubeadm completion bash)

Helm

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
helm repo add hc https://charts.helm.sh/stable