通过kubeadm安装K8s集群
kubeadm
是官方社区推出的一个用于快速部署kubernetes集群的工具。这个工具能通过两条指令快速完成一个kubernetes集群的部署。
本例子中使用centos7系统安装k8s集群
一、系统初始化设置:
参考k8s二进制部署章节:系统初始化
二、docker安装:
参考k8s二进制部署:docker安装
三、机器IP信息:
主机名 | IP | 节点类型 | 最低配置 |
k8s-master1 | 192.168.15.215 | master1节点 | 1G2CPU |
k8s-master2 | 192.168.15.216 | master2节点 | 1G2CPU |
k8s-master3 | 192.168.15.217 | master3节点 | 1G2CPU |
k8s-worker1 | 192.168.15.218 | worker1节点 | 1G2CPU |
k8s-worker2 | 192.168.15.219 | worker2节点 | 1G2CPU |
k8s-worker3 | 192.168.15.221 | worker3节点 | 1G2CPU |
VIP | 192.168.15.253 | 部署在master节点 |
#注意:master节点至少要2个cpu,否则报错
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
四、安装keepalived和nginx:
keepalived直接yum即可,keepalived配置文件可参考二进制安装一篇,nginx需要编译安装,因为需要stream模块,Nginx编译安装参考:Nginx编译安装
nginx配置文件内容如下:
events {
worker_connections 1024;
}
stream {
log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
access_log /var/log/nginx/k8s-access.log main;
upstream k8s-apiserver {
server 192.168.15.215:6443; # Master1 APISERVER IP:PORT
server 192.168.15.216:6443; # Master2 APISERVER IP:PORT
server 192.168.15.217:6443; # Master3 APISEVER IP:PORT
}
server {
listen 16443; # 由于nginx与master节点复用,这个监听端口不能是6443,否则会冲突
proxy_pass k8s-apiserver;
}
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
keepalived中配置nginx健康状态检测脚本,如下:
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20 #脚本返回状态码为1,那么权重下降20,实现VIP飘逸
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.15.253/24
}
track_script {
check_nginx
}
}
check_nginx脚本内容如下:
#!/bin/bash
count=$(ss -antp |grep 16443 |egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
exit 1
else
exit 0
fi
注意:如果是单master,那么就不需要安装 keepalived和nginx
五、安装etcd:
本教程中etcd采用单独安装的方式,安装方法参考二进制部署章节https://www.ywdevops.cn/index.php/2021/06/29/k8s-2/
六、安装k8s组件:
1、下载k8s组件:
我们需要安装kubeadm, kubelet, kubectl,版本需要一致。在可以连外网的机器上下载组件。
添加kubernetes yum源:
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes Repo
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
enabled=1
EOF
查看kubeadm版本
yum list kubeadm --showduplicates
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/5-1.png)
我们下载1.20.8版本(也可根据需要下载任何版本)
yum install --downloadonly --downloaddir ~/k8s/kubernetes kubeadm-1.20.8-0
在根据上述方式查找kubelet、kubectl版本,以及依赖包,并下载
yum install --downloadonly --downloaddir ~/k8s/kubernetes kubelet-1.20.8-0
yum install --downloadonly --downloaddir ~/k8s/kubernetes kubectl-1.20.8-0
yum install --downloadonly --downloaddir ~/k8s/kubernetes kubernetes-cni-0.8.7-0
yum install --downloadonly --downloaddir ~/k8s/kubernetes cri-tools-1.13.0-0
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/4-1.png)
2、安装k8s组件:
将上图中的rpm包拷贝到每一个节点,执行如下命令安装
yum install ~/k8s/kubernetes/*.rpm
执行完成后, kubeadm, kubectl, kubelet就已经安装好了
3、 设置kubelet的开机启动。我们并不需要启动kubelet,就算启动,也是不能成功的。执行kubeadm命令,会生成一些配置文件 ,这时才会让kubelet启动成功的。
systemctl enable kubelet
4、拉取镜像:
执行kubeadm时,需要用到一些镜像,我们需要提前准备
查看需要依赖哪些镜像:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/5-2.png)
由于国内访问不了k8s.gcr.io地址,因此需要通过国内镜像地址,或者直接通过docker hub地址拉取镜像也可以,本例子已经从docker hub上拉取了镜像,并tag成k8s.gcr.io的地址类型,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/6-1.png)
七、部署k8s集群:
1、 获取默认配置文件 :
kubeadm config print init-defaults > kubeadm-config.yaml
kubeadm-config.yaml文件的内容如下:
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.15.215
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: k8s-master1
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
certSANs:
- k8s-master1
- k8s-master2
- k8s-master3
- 192.168.15.215
- 192.168.15.216
- 192.168.15.217
- 192.168.15.253
- 127.0.0.1
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "192.168.15.253:16443" #vip
controllerManager: {}
dns:
type: CoreDNS
etcd:
external:
endpoints:
- https://192.168.15.215:2379
- https://192.168.15.216:2379
- https://192.168.15.217:2379
caFile: /opt/etcd/ssl/etcd-ca.pem
certFile: /opt/etcd/ssl/server.pem
keyFile: /opt/etcd/ssl/server-key.pem
imageRepository: registry.aliyuncs.com/google_containers #阿里云仓库
kind: ClusterConfiguration
kubernetesVersion: v1.20.8
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16 #pod网段
serviceSubnet: 10.96.0.0/12 #server网段
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs #开启ipvs模式
---
#注意:在初始化集群之前,需要确保当前机器可以登录镜像仓库,否则拉取镜像失败
也可以使用命令将旧的kubeadm-config.yaml转换为新的文件,执行命令如下:
kubeadm config migrate --old-config kubeadm-config.yaml --new-config new.yaml
2、将从外网下载镜像导入到机器中,执行命令如下:
dokcer load -i 镜像名
#注意:如果上面初始化文件中配置了镜像仓库地址,就不用再次load了
3、 初始化集群:
kubeadm init --config kubeadm-config.yaml
#如果集群初始化失败需要重置集群,可执行下面命令
kubeadm reset -f
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
如果初始化成功,可以看到内容如下:
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join 192.168.15.253:16443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:9363682fcdbfedd6e059d7428d859d5b0ae5388641dcd098b6876d89461b0625 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.15.253:16443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:9363682fcdbfedd6e059d7428d859d5b0ae5388641dcd098b6876d89461b0625
注意:master节点加入命令和Node节点加入命令的唯一区别就是master节点加入命令多了一个参数 --control-plane,其余都是一摸一样的
注意:如果初始化卡在这个位置:[kubelet-check] Initial timeout of 40s passed., 则说明是初始化配置文件中的controlPlaneEndpoint不通,可排查下
4、 在其它两个master节点创建以下目录 :
mkdir -p /etc/kubernetes/pki/
5、 把主master节点证书分别复制到其余master节点 :
scp -r /etc/kubernetes/pki/ca.* root@192.168.15.216:/etc/kubernetes/pki/
scp -r /etc/kubernetes/pki/sa.* root@192.168.15.216:/etc/kubernetes/pki/
scp -r /etc/kubernetes/pki/front-proxy-ca.* root@192.168.15.216:/etc/kubernetes/pki
scp -r /etc/kubernetes/pki/etcd/ca.* root@192.168.15.216:/etc/kubernetes/pki/etcd
scp -r /etc/kubernetes/admin.conf root@192.168.15.216:/etc/kubernetes/
6、 其他master节点加入集群执行以下命令 :
kubeadm join 10.88.15.253:8443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:9363682fcdbfedd6e059d7428d859d5b0ae5388641dcd098b6876d89461b0625 --control-plane
7、 所有master节点执行以下命令(管理集群,查看集群等),node节点随意 :
#root用户执行以下命令:
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source .bash_profile
#非root用户可以执行以下命令:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
8、 node节点加入集群执行以下命令(要安装kubeadm、kubelet、kubectl) :
kubeadm join 10.88.15.253:8443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:9363682fcdbfedd6e059d7428d859d5b0ae5388641dcd098b6876d89461b0625
注意:如果加入时卡在了这个命令位置,[preflight] Running pre-flight checks,说明token已经过期,此时可以执行下面命令重新生成token和hash的值
kubeadm token create
kubeadm token list
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
生成后使用新的token和hash值再次执行命令加入集群即可
如果加入node节点,出现如下错误: error execution phase kubelet-start: error uploading crisocket: timed out waiting for the condition
To see the stack trace of this error execute with –v=5 or higher,此时可以按照如下步骤执行,如下:
swapoff -a
kubeadm reset
systemctl daemon-reload
systemctl restart kubelet
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
#执行完成后重新加入集群即可
9、加入完成后,在master节点执行命令查看集群资源,如下:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/7-1.png)
从上图可以看出,STATUS显示NotReady,因为还没有安装网络组件
执行命令kubectl get cs 查看集群状态可以看出显示如下:
![](https://www.gycysygg.icu/wp-content/uploads/2021/12/2.png)
出现这种情况,是/etc/kubernetes/manifests/下的kube-controller-manager.yaml和kube-scheduler.yaml设置的默认端口是0导致的,解决方式是注释掉对应的port即可,操作如下:
![](https://www.gycysygg.icu/wp-content/uploads/2021/12/3.png)
执行命令kubectl get po -n kube-system可以看到coredns处于pending状态,因为没有安装calico
![](https://www.gycysygg.icu/wp-content/uploads/2021/12/1.png)
10、安装calico网络插件:下载文件,执行命令如下:
#注意:此calico是针对50个节点之内的
curl https://docs.projectcalico.org/manifests/calico.yaml -O
修改pod CIDR地址,默认是192.168.0.0/16,需要修改成我们自己的,先打开注释,修改自定义的pod网段地址,如图:
![](https://www.ywdevops.cn/wp-content/uploads/2022/05/6-3.png)
里面的镜像地址修改为自己的仓库地址,本例子中用的阿里云镜像仓库(不需要secret认证),如图:
![](https://www.ywdevops.cn/wp-content/uploads/2022/05/7-2.png)
如果是个人仓库还需要在镜像拉取策略位置要设置仓库认证名称(Deployment和DaemonSet位置都要设置)和拉取策略(也可以不设置默认是Always),如图:
![](https://www.jinengpai.cn/wp-content/uploads/2021/10/48.png)
注意:需要创建仓库认证文件secret.yml,然后配置在calico中,这样才可以顺利将镜像拉去下来,参考二进制部署中的配置说明https://www.ywdevops.cn/index.php/2021/06/29/k8s-2/
最后执行命令kubectl apply -f calico.yaml即可,执行完成后可以看到coredns也恢复正常了,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/11-1.png)
各个节点状态都变成了Ready,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/12-1.png)
注意:如果出现如下错误calico/node is not ready: BIRD is not ready: BGP not established,表示calico没有 发现实际真正的网卡 ,可用如下方式解决,如图:
![](https://www.jinengpai.cn/wp-content/uploads/2021/09/56.png)
如果calico的控制器pod calico-kube-controllers提示错误如下:
Failed to create pod sandbox: rpc error: code = Unknown desc = [failed to set up sandbox container “70a2175a467ba631594c6f661ff612e15eed9d5f31332061ef7d2b399d5cacdb” network for pod “calico-kube-controllers-dbc86d6cc-7cbs9”: networkPlugin cni failed to set up pod “calico-kube-controllers-dbc86d6cc-7cbs9_kube-system” network: error getting ClusterInformation: connection is unauthorized: Unauthorized, failed to clean up sandbox container “70a2175a467ba631594c6f661ff612e15eed9d5f31332061ef7d2b399d5cacdb” network for pod “calico-kube-controllers-dbc86d6cc-7cbs9”: networkPlugin cni failed to teardown pod “calico-kube-controllers-dbc86d6cc-7cbs9_kube-system” network: error getting ClusterInformation: connection is unauthorized: Unauthorized
解决方法:
- kubelet delete -f calico.yaml #卸载calico
- rm -rf /etc/cni/net.d/* #删除全部节点的calico残留配置文件
- modprobe -r ipip #删除tun10网卡
- reboot 或者systemctl restart kubelet
- kubectl apply -f calico.yaml #最后在重新部署calico
注:k8s 1.20.8版本可使用calico的3.19.1 ,k8s 1.23.5版本可用calico的3.25.0版本
metrics部署:
在新版的k8s中,资源采集均使用Metirc-server,可以通过Metirc采集节点和Pod的内存、磁盘、cpu和网络使用率
首先将mastere1节点的front-proxy-ca.crt拷贝到所有Node节点
scp /etc/kubernetes/pki/front-proxy-ca.crt root192.168.15.218:/etc/kubernetes/pki
github.com下载metrics的yaml文件,地址如下:
https://github.com/kubernetes-sigs/metrics-server/releases/tag/v0.4.4
#名称为:components.yaml
修改文件components.yaml,内部的镜像地址改为自己的仓库地址(需要提前把镜像下载回来传入仓库),然后加入指定证书的参数,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/15-1.png)
注:不加证书参数可能获取不到度量指标
执行命令kubectl create -f components.yaml创建Pod即可,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/16-1.png)
注意:如果镜像拉取不成功,那就手动将镜像拉取到每个节点上即可,注意看镜像拉取策略imagePullPolicy,如果是IfNotPresent,那么如果从仓库拉取不成功就会寻找本地镜像
运行成功后,执行命令kubectl top node 可以查看所有节点的资源情况,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/20-1.png)
执行命令kubectl top po -A 可以查看所有pod的资源情况,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/21.png)
注:-A 表示所有命名空间
至此:k8s集群已经部署完成,下面的dashboard可根据需要进行部署
dashboard部署
将文件下载回来,一共两个文件,dashboard-user.yaml和dashboard.yaml,修改dashboard.yaml中的镜像地址为本地地址,一共两个,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/17-1.png)
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/18-1.png)
执行命令创建pod,如下:
kubectl create -f dashborad-user.yaml dashboard.yaml
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/19.png)
注意:如果镜像拉取不成功,可检查下拉取策略是否为IfNotPresent,建议采用此策略
部署完成后,需要修改谷歌浏览器的配置,然后才可以访问自签名的https页面,在启动文件后面添加参数–test-type –ignore-certificate-errors,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/22-1.png)
然后更改kubernetes-dashboard的svc为NodePort,否则访问不了,执行命令如下:
#首先查看下svc
kubectl get svc -n kubernetes-dashboard
#编辑svc
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
#编辑后,修改最下方的type:ClusterIP 为type:NodePort
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/23-1.png)
再次查看svc可以看到已经变成NodePort类型,映射到宿主的端口为30500,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/24-1.png)
此时通过vip地址加端口即可访问dashboard,https://192.168.15.253:30500如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/25-1.png)
注意:通过https来访问
查看登录token,命令如下:
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/28.png)
将此token输入后,点击登录即可,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/27-1.png)
修改proxy模式为ipvs
首先查看下默认的模式,执行命令如下:
curl 127.0.0.1:10249/proxyMode
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/29.png)
输入命令编辑kube-proxy,修改模式为ipvs,如下:
#查看comfigmap情况
kubectl get cm -n kube-system
#编辑kube-proxy,修改模式
kubectl edit cm kube-proxy -n kube-system
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/30.png)
执行命令滚动更新,如下:
kubectl patch daemonset kube-proxy -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}" -n kube-system
再次查看模式,已经变成ipvs,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/31.png)
七、集群可用性验证:
1、首先通过命令kubectl get po –all-namespace(或者-A参数)查看所有容器都已启动,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/13-1.png)
2、验证下网络情况,首先查看k8s的service ip情况,执行命令如下:
kubectl get svc
#k8s的IP地址一般为cluster ip的第一个IP地址
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/32.png)
验证每台机器到此IP的443端口是否通,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/33.png)
查询coredns的serviceip 地址,执行命令如下:
kubectl get svc -n kube-system
#coredns的IP地址一般为clusterip 的第10个IP地址
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/34.png)
验证每台机器到此IP的53端口是否通,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/35.png)
3、验证其余机器到某台机器的pod 是否通(跨服务器访问),首先查看pod地址,如图:
kubctl get po -A -o wide //查询详细信息
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/36.png)
从上图可以看出,在master2机器上有一个Pod ,地址为172.169.115.66,然后在其他所有节点上ping此IP地址,看是否通,如图:
![](http://www.jinengpai.cn/wp-content/uploads/2021/07/37.png)
经过测试,所有节点都通,说明跨服务器访问没问题
4、接下来验证pod和pod之间是否通,选择其他任意一台机器,进入pod中,然后ping master节点的172.169.115.66,执行命令如下:
通过如下组件可实现固定pod的ip/mac地址:
https://github.com/google-fabric