总体流程一览
主要流程如下:
1.准备云主机,升级CentOS系统到7.9
2.所有节点上安装Docker和Kubeadm,拉取相关镜像
3.在Master节点初始化集群,包括kubectl和部署CN容器网络插件
4.把Node节点加入k8s集群
可视化界面和私有镜像仓库请参考其他文章:
1.部署Dashboard Web 页面,可视化查看Kubernetes资源,看我下一篇文章:k8s dashboard安装
2.部署Harbor私有仓库,存放镜像资源(非必要,省略介绍)
下面,开始介绍各流程详细配置步骤。
环境准备
云主机
云服务器 | 区域 | CentOS | 节点类型 | 配置 | 公网IP | 安装工具 |
腾讯云 | 上海三区 | 7.9 | master01 | 2C4G | 101.34.112.190 | docker、kubeadm、kubelet、kubectl、flannel |
同上 | 上海二区 | 7.9 | node01 | 1C2G | 81.68.126.69 | 同上 |
同上 | 上海二区 | 7.9 | node02 | 1C2G | 81.68.92.49 | 同上 |
CentOS升级
如果低于CentOS 7.9
,请先升级:
$ yum update -y
$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
PS:请务必不要跳过这步,低版本的CentOS安装Kubeadm时很可能会失败。作者就是失败之后升级CentOS才成功了!!
所有节点CentOS设置
基础设置
PS:该步骤基于:
CentOS Linux release 7.9.2009 (Core)
,7.2 - 7.6 版本好像会失败,如果中途不成功,请考虑升级更换CentOS版本!
可以创建 k8s-pre-install-centos.sh 脚本,一键设置:
$ vim k8s-pre-install-centos.sh
#!/bin/sh
function set_base(){
# 关闭防火墙,PS:如果使用云服务器,还需要在云服务器的控制台中把防火墙关闭了或者允许所有端口。
systemctl stop firewalld
systemctl disable firewalld
# 关闭SELinux,这样做的目的是:为了让容器能读取主机文件系统。
setenforce 0
# 永久关闭swap分区交换,kubeadm规定,一定要关闭
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
# iptables配置
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
net.ipv4.ip_forward = 1
EOF
# iptables生效参数
sysctl --system
}
set_base
执行上述脚本:
$ chmod 777 k8s-pre-install-centos.sh && ./k8s-pre-install-centos.sh
主机名设置
修改主机名
master执行:
hostnamectl set-hostname master01
节点1执行:
hostnamectl set-hostname node01
节点2执行:
hostnamectl set-hostname node02
修改hosts文件
每台机器上都要执行:
$ vim /etc/hosts
101.34.112.190 master01
81.68.126.69 node01
81.68.92.49 node02
PS:请更换为自己的公网IP(注意是公网IP,不是内网)!
所有节点安装Docker
k8s支持 3种容器运行时,这里我们优先使用熟悉的 Docker
作为容器运行时。请确保CentOS 7以上,最新要求以 官方 为主。
安装yum仓库
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
安装docker
包括cli、engine、docker compose等
$ sudo yum install docker-ce-20.10.14-3.el7 docker-ce-cli-20.10.14-3.el7 containerd.io docker-compose-plugin
ps:本教程使用的是docker版本:20.10.14
配置Docker守护程序
尤其是使用 systemd
来管理容器的 cgroup,另外还要配置阿里云镜像源,加快拉取速度!
$ sudo mkdir /etc/docker
$ cat <<EOF | sudo tee /etc/docker/daemon.json
{
"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
- registry-mirrors:镜像加速。
- cgroupdriver:使用systemd。
- log-driver:使用json日志,大小为100m。
启动docker,并设置为开机启动
$ sudo systemctl enable docker
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$ systemctl status docker # 确保是running状态
确认Cgroup Driver为systemd
$ docker info | grep "Cgroup Driver"
Cgroup Driver: systemd
PS:因为k8s是默认systemd作为cgroup driver,如果Docker使用另外的驱动,则可能出现不稳定的情况。
所有节点安装kubeadm
为保证不过期,请最终以 官方文档 为主:
配置yum源(使用aliyun,google你知道的)
$ cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
$ yum makecache # 更新yum
安装kubeadm, kubelet, kubectl
$ sudo yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6 --disableexcludes=kubernetes
PS:k8s升级很快,为了保证教程正确,请使用相同版本。
启动klubelet,并设置为开机启动
$ sudo systemctl start kubelet
$ sudo systemctl enable kubelet
PS:kubeadm 将使用 kubelet 服务以容器方式部署和启动 Kubemetes 的主要服务。
所有节点拉取Docker镜像
ps:该1.23.6版本,需要
docker为20
,超过的不保证成功
拉取Docker镜像
查看初始化需要的镜像
$ kubeadm config images list
k8s.gcr.io/kube-apiserver:v1.23.6
k8s.gcr.io/kube-controller-manager:v1.23.6
k8s.gcr.io/kube-scheduler:v1.23.6
k8s.gcr.io/kube-proxy:v1.23.6
k8s.gcr.io/pause:3.6
k8s.gcr.io/etcd:3.5.1-0
k8s.gcr.io/coredns/coredns:v1.8.6
替换k8s镜像源
k8s模式镜像仓库是 k8s.gcr.io
,由于众所周知的原因是无法访问的。
故这里需要创建配置 kubeadm-config-image.yaml 替换成阿里云的源:
$ vim kubeadm-config-image.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
# 默认为k8s.gcr.io,但是网络不通,所以要替换为阿里云镜像
imageRepository: registry.aliyuncs.com/google_containers
确认镜像仓库改变
再查看,发现镜像的地址变了,才能执行下一步:
$ kubeadm config images list --config kubeadm-config-image.yaml
registry.aliyuncs.com/google_containers/kube-apiserver:v1.23.6
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.23.6
registry.aliyuncs.com/google_containers/kube-scheduler:v1.23.6
registry.aliyuncs.com/google_containers/kube-proxy:v1.23.6
registry.aliyuncs.com/google_containers/pause:3.6
registry.aliyuncs.com/google_containers/etcd:3.5.1-0
registry.aliyuncs.com/google_containers/coredns:v1.8.6
拉取镜像
$ kubeadm config images pull --config kubeadm-config-image.yaml
在 所有机器
上执行,把这些镜像提前拉好。
Master节点初始化集群
生成默认配置 kubeadm-config.yaml
并更改下面几项:
$ kubeadm config print init-defaults > kubeadm-config.yaml
-
kubernetes-version
:集群版本,上面安装的kubeadm版本必须小于等于这里的 -
pod-network-cidr
:pod资源的网段,需与pod网络插件的值设置一致。通常,Flannel网络插件的默认为10.244.0.0/16,Calico插件的默认值为192.168.0.0/16; -
api-server
:使用Master作为api-server,所以就是master机器的IP地址。 -
image-repository
:拉取镜像的镜像仓库,默认是k8s.gcr.io。 -
nodeRegistration.name
:改成master01
最终如下:
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 101.34.112.190 # 指定master节点的IP地址(公网)
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
imagePullPolicy: IfNotPresent
name: master01 # 改成master的主机名
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers # 默认为k8s.gcr.io,但是网络不通,所以要替换为阿里云镜像
kind: ClusterConfiguration
kubernetesVersion: 1.23.6 # 指定kubernetes版本号,使用kubeadm config print init-defaults生成的即可
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16 # 指定pod网段,10.244.0.0/16用于匹配flannel默认网段
scheduler: {}
上面的配置等价于:
$ kubeadm init \
--kubernetes-version=v1.23.6 \
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=101.34.112.190 --ignore-preflight-errors=Swap
或者1核CPU Master初始化(--ignore-preflight-errors=NumCPU
这个如果是1核的ECS服务器一定要添加,不然会报错,因为K8S要求最低核数是2核)::
$ kubeadm init \
--kubernetes-version=v1.23.6 \
--apiserver-advertise-address=101.34.112.190
--ignore-preflight-errors=NumCPU \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--image-repository registry.aliyuncs.com/google_containers \
--v=6
PS:建议通过配置文件的方式来操作,命令行不直观。
检查环境
$ kubeadm init phase preflight --config=kubeadm-config.yaml
这个命令会检查配置文件是否正确,以及系统环境是否支持kubeadm的安装。
初始化kubeadm集群
只需要在master上执行如下命令:
$ kubeadm init --config=kubeadm-config.yaml
PS:这里是最难的,作者卡在这里卡了一整天,查阅各种资料才解决,所以如果你也失败了,比较正常,这里是相比于内网部署k8s,公网最麻烦也是最难的点,这一步成功了,后面也没啥了。
到这里,会有2种结果:
-
如果是内网
,上面的docker版本,kubeadm版本没错的话,会成功,直接跳到4步骤。 - 如果在
云服务器
(腾讯云,阿里云)上,一定会失败(原因和办法在这里)
:
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests”
// ...
[kubelet-check] Initial timeout of 40s passed.
提示:请一定先执行上面的初始化(目的是为了生成k8s的配置文件
,否则下面的步骤中你会找不到etcd.yaml),失败后再执行下面的步骤!!
云服务器初始化失败解决版本
1)编辑etcd配置文件
配置文件位置:/etc/kubernetes/manifests/etcd.yaml
- --listen-client-urls=https://127.0.0.1:2379,https://101.34.112.190:2379
- --listen-peer-urls=https://101.34.112.190:2380
改成
- --listen-client-urls=https://127.0.0.1:2379
- --listen-peer-urls=https://127.0.0.1:2380
引用 在腾讯云安装K8S集群 :
此处"118.195.137.68"为腾讯云公网ip,要关注的是"–listen-client-urls"和"–listen-peer-urls"。需要把–listen-client-urls后面的公网IP删除,把–listen-peer-urls改成127.0.0.1:2380
原因是因为腾讯云只要选择VPC网络均是采用NAT方式将公网IP映射到私人网卡的,有兴趣的同学可以了解下NAT。这也就是为什么很多同事无法在腾讯云或阿里云上安装k8s集群的原因
2)手工停止已启动的进程
# 先停止kubelet
$ systemctl stop kubelet
# 把所有kube的进程杀掉
$ netstat -anp |grep kube
请注意,不要执行 kubeadm reset,先 systemctl stop kubelet
,然后手动通过 netstat -anp |grep kube
来找pid,再通过 kill -9 pid
强杀。否则又会生成错误的etcd配置文件
,这里非常关键!!!
3)重新初始化,但是跳过etcd文件已经存在的检查:
# 重新启动kubelet
$ systemctl start kubelet
# 重新初始化,跳过配置文件生成环节,不要etcd的修改要被覆盖掉
$ kubeadm init --config=kubeadm-config.yaml --skip-phases=preflight,certs,kubeconfig,kubelet-start,control-plane,etcd
成功初始化
如果所有配置都正常,很快会输出下面的信息(秒级别
)代表了成功,否则大概率是失败(由于网络超时等):
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/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.200:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:af2a6e096cb404da729ef3802e77482f0a8a579fa602d7c071ef5c5415aac748
保存上面输出的token和sha256值。
也就是下面这一段,这段命令主要是让node节点加入k8s集群:
kubeadm join 101.34.112.190:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:af2a6e096cb404da729ef3802e77482f0a8a579fa602d7c071ef5c5415aac748
常见错误
Initial timeout of 40s passed
- 可能1:检查镜像版本,可能是不匹配或者本地替换tag出错造成的了,或者是因为公网IP ETCD无法启动造成的。执行:
journalctl -xeu kubelet
查看具体错误,或者时候journalctl -f -u kubelet
查看初始化的实时输出,下次初始化之前执行kubeadm reset
重置。 - 可能2:CentOS版本太低,推荐
7.8
以上。我在7.2和7.5都失败了
,执行yum update -y
升级到7.9才成功。
证书忘记
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2> /dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
token忘记
kubeadm token list
配置kubectl(master)
准备配置文件
kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm 部署的集群为其生成了一个具有管理员权限的认证配置文件 /etc/kubernetes/admin.conf,它可由 kubectl 通过默认的 “$HOME/.kube/config” 的路径进行加载。
拷贝配置文件到kubectl默认加载路径:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
使用kubectl查看集群信息
在Master节点上执行,输出集群信息:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01 NotReady control-plane,master 15m v1.23.6
$ kubectl get cs
etcd-0 Healthy {"health":"true","reason":""}
controller-manager Healthy ok
scheduler Healthy ok
这里STATUS是NotReady是因为还没有配置网络的原因,接下来会介绍。
安装CN网络(master)
$ curl https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml>>kube-flannel.yml
$ chmod 777 kube-flannel.yml
$ kubectl apply -f kube-flannel.yml
等待几分钟,再查看Master节点状态,由NotRead变成了Ready状态:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01 Ready control-plane,master 15m v1.23.6
允许master节点部署pod
此时k8s master节点安装完毕(为了不浪费云服务器资源
,需要让master节点能部署pod,需要运行以下命令)。
- 查看调度策略
$ kubectl describe node|grep -E "Name:|Taints:"
Name: master01
Taints: node-role.kubernetes.io/master:NoSchedule
- NoSchedule: 一定不能被调度
- PreferNoSchedule: 尽量不要调度
- NoExecute: 不仅不会调度, 还会驱逐Node上已有的Pod
- 更改master节点可被部署pod
$ kubectl taint nodes --all node-role.kubernetes.io/master-
- 查看是否生效
$ kubectl describe node|grep -E "Name:|Taints:"
Name: master01
Taints: <none>
把Node节点加入集群
在node上执行上面kubeadm输出的命令(注意token和sha256值不同):
$ kubeadm join 192.168.1.200:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:af2a6e096cb404da729ef3802e77482f0a8a579fa602d7c071ef5c5415aac748
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
此时,在master执行以下命令,可以看到node节点已经加入成功了:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01 Ready control-plane,master 60m v1.23.6
node01 NotReady <none> 54s v1.23.6
等待5分钟左右,node01的状态变成Ready。
另外一台Node节点机器,重复改步骤加入集群即可!
测试集群
创建个nginx Pod
在master节点运行以下命令:
$ kubectl run --image=nginx nginx-app --port=80
$ kubectl run --image=nginx nginx-app1 --port=81
然后再运行:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app 0/1 ContainerCreating 0 18s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-app 1/1 Running 0 26s
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app 1/1 Running 0 57s 10.244.1.2 node01 <none> <none>
可以看到2个pod已经是运行状态,证明k8s集群成功安装
Dashboard可视化界面安装