简介
Kubernetes是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本。它是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。
通过Kubernetes你可以:
快速部署应用
快速扩展应用
无缝对接新的应用功能
节省资源,优化硬件资源的使用
Kubernetes 特点:
- 可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)
- 可扩展: 模块化, 插件化, 可挂载, 可组合
- 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展
部署
准备工作
注意,不特殊说明就是master和每个node节点都要做的操作。
1.安装docker
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装 Docker-CE
sudo apt-get -y update
# Step 5: 查看支持安装的Docker版本
apt-cache madison docker-ce
# Step 6: 安装指定版本的docker-ce
sudo apt-get -y install docker-ce=5:19.03.13~3-0~ubuntu-focal
上面是参考阿里云镜像仓库docker的安装方法,只有在最后安装的指定版本不同。
可以考虑普通用户加入docker组,这样就不用每次都sudo docker了
#添加docker用户组,一般已存在,不需要执行:
sudo groupadd docker
#将登陆用户加入到docker用户组中:
sudo gpasswd -a $USER docker
#更新用户组:
newgrp docker
#测试docker命令是否可以使用
docker version
2.docker相关设置
$ vi /etc/docker/daemon.json
# 下面注释的文字不要放到json文件里
{
# 换源
# 国内网络问题,pull镜像大概率速度很慢,可以添加加速仓库
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://ustc-edu-cn.mirror.aliyuncs.com",
"https://ghcr.io",
"https://mirror.baidubce.com"
],
# 更换cgroup
"exec-opts": ["native.cgroupdriver=systemd"]
}
关于更换cgroup:
两种cgroup机制:cgroupfs
和systemd
,docker默认使用的是cgroupfs,而k8s默认使用的是systemd,所以修改docker的cgroup机制为systemd,保持docker和k8s的cgroup机制一致,不修改的话在下面的kubeadm init
时可能会报错。
使用docker info | grep "Cgroup Driver"
命令查看docker修改配置文件前后使用的cgroup机制。
$ docker info | grep "Cgroup Driver"
Cgroup Driver: cgroupfs
# 修改后
$ docker info | grep "Cgroup Driver"
Cgroup Driver: systemd
更新完文件记得重启下docker服务。
service docker restart
3.安装k8s相关工具
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet=1.21.2-00 kubeadm=1.21.2-00 kubectl=1.21.2-00
上面是参考阿里云镜像仓库k8s的安装方法,只有在最后安装的指定版本不同。
k8s 在1.24版本开始去掉了自带的
dockershim
,新版本需要自己配置,为了简便部署,这里采用了1.21.2
版本。
设置下开机自启:
sudo systemctl enable kubelet && sudo systemctl start kubelet
4.k8s要求关闭swap
临时
swapoff -a
永久
swapoff -a && sysctl -w vm.swappiness=0 # 关闭swap
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab # 取消开机挂载swap
注意:swapoff -a 命令只会临时关闭swap,如果采取该方式关闭swap,在重启系统后swap又会开启,将导致k8s启动失败。如果k8s启动失败,可以关闭swap后运行以下命令(该命令与部署无关,仅作提醒)
systemctl daemon-reload
systemctl restart kubelet
5.设置系统参数允许路由转发,不对网桥的数据进行处理
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
6.关闭防火墙
systemctl stop ufw
systemctl disable ufw
配置集群网络
准备多台可以互相ping通的机器,设置静态ip。
vi /etc/hosts
#添加以下内容
192.168.1.131 master
192.168.1.132 node1
192.168.1.133 node2
分别登录每台机器,测试下是否可以ping通。
集群初始化
master初始化
在Master节点上执行集群初始化命令,node节点不需要。
--image-repository registry.aliyuncs.com/google_containers
指定国内镜像源,懂得都懂。--pod-network-cidr
k8s自身不携带CNI(Container Network Interface),所以需要依赖第三方的插件,例如比较常用的flannel。
使用flannel需要在集群初始化时指定,指定pod使用的IP地址块。如果在没有指定该参数的情况下初始化了集群,那么将无法成功安装flannel,只能推倒重来。IP地址块参数自行决定,只要不和现有的IP冲突即可。
最终的初始化命令如下:
$ kubeadm init --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr 10.244.0.0/16
可能会出现的报错
1.第一种
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
这是因为docker和k8s的cgroupfs不一致,解决方法看这里docker相关设置
2.虽然指定了国内镜像源,但还是有可能造成某个镜像拉取失败
如果直接重试的话,会有这样的报错:
[ERROR: Port XXX is in use]
[ERROR: **.yaml already exists]
解决办法:
kubeadm reset # 按y
然后再次kubeadm init
。
一切顺利的话最终是这样的
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.31.229:6443 --token ohqy5u.mzmt30y4if4w57s5 \
--discovery-token-ca-cert-hash sha256:207149beb4575986ed46573ff65370f957e253acedf72309c260b3b3ce68638a
注意保存下最后加入集群的凭证。
然后根据log提示:
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
或者写入/etc/profile
(永久生效)。
systemctl enable kubelet # 启动kubelet 设置为开机自启动
systemctl start kubelet # 启动k8s服务程序
查看下当前节点信息:
root@ubuntu:# kubectl get nodes
NAME STATUS ROLES AGE VERSION
ubuntu NotReady control-plane,master 12m v1.21.2
刚初始化完master确实是NotReady状态。
部署集群的网络
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
网络不通的话,也可以想办法把找到文件内容,写入到本地文件在进行apply
。
flannel容器初始化需要的时间比较长,可以稍微等等,不要急着进行别的操作。
按理来说,这样操作之后master的状态应该是Ready了,但是哪有那么顺利,我等了二十分钟也不行。。
踩坑经验
Node节点加入集群
直接在Node节点上执行刚才保存的kubeadm join命令即可:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
如果没有记录kubeadm join命令,可以通过以下方式获取到相关参数:
手动获取获取token:
kubeadm token list
手动获取ca-cert:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
重新生成完整的加入集群的命令:
kubeadm token create --print-join-command
查看集群工作状态
1.查看集群Node信息
kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready <none> 31m v1.21.2
node2 Ready <none> 27m v1.21.2
ubuntu Ready control-plane,master 66m v1.21.2
如果Node节点的status不为ready,可以稍微等一等,需要一定时间适配。
2.查看pod信息
root@ubuntu:~# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-pj5pn 1/1 Running 0 37m
kube-system coredns-59d64cd4d4-7flw8 1/1 Running 0 45m
kube-system coredns-59d64cd4d4-m5c5k 1/1 Running 0 45m
kube-system etcd-ubuntu 1/1 Running 0 45m
kube-system kube-apiserver-ubuntu 1/1 Running 0 45m
kube-system kube-controller-manager-ubuntu 1/1 Running 0 35m
kube-system kube-proxy-xqspk 1/1 Running 0 45m
kube-system kube-scheduler-ubuntu 1/1 Running 0 35m
应该输出截图中的内容,需要注意的是如果网络配置没有问题,那么上面的容器应该均为Running状态。flannel容器初始化需要的时间比较长,可以稍微等等,不要急着进行别的操作。
节点角色设置
初始化完成后默认所有节点都是没有角色的,需要手动设置节点角色.
设置Master节点:
kubectl label nodes your_node_name node-role.kubernetes.io/master=
设置Node节点:
kubectl label nodes your_node_name node-role.kubernetes.io/node=
可以设置一个节点同时为master和node。
最后查看下集群状态
root@ubuntu:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready node 31m v1.21.2
node2 Ready node 27m v1.21.2
ubuntu Ready control-plane,master 66m v1.21.2
查看kubelet日志
journalctl -f -u kubelet # 查看kubelet日志
journalctl -f -u kubelet > kubelet.log # 将日志输出到本地文件查看
踩过的坑
集群网络初始化错误
root@ubuntu:~# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
# 看起来是应用成功了,也等了足够的初始化时间,但是为什么master还是NotReady呢?
root@ubuntu:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
ubuntu NotReady control-plane,master 18m43s v1.21.2
到底是哪里出了问题?
先看下所有的pod:
root@ubuntu:# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-pj5pn 0/1 Init:1/2 0 8m56s
kube-system coredns-59d64cd4d4-7flw8 0/1 Pending 0 14m
kube-system coredns-59d64cd4d4-m5c5k 0/1 Pending 0 14m
可以看到kube-flannel-ds-pj5pn
过了很久还在init
,肯定有问题!
此时查看kubelet的log:
$ journalctl -f -u kubelet
5月 06 23:58:32 ubuntu kubelet[33628]: E0506 23:58:32.866007 33628 kubelet.go:2211] "Container runtime network not ready" networkReady="NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized"
更加印证了flannel有问题!
查看下对应pod的详细信息:
$ kubectl describe pod kube-flannel-ds-pj5pn -n kube-flannel
Name: kube-flannel-ds-pj5pn
Namespace: kube-flannel
Priority: 2000001000
Priority Class Name: system-node-critical
......
# 中间还有N多信息,这里省略了。
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 21m default-scheduler Successfully assigned kube-flannel/kube-flannel-ds-pj5pn to ubuntu
Normal Pulling 21m kubelet Pulling image "docker.io/flannel/flannel-cni-plugin:v1.1.2"
Normal Pulled 20m kubelet Successfully pulled image "docker.io/flannel/flannel-cni-plugin:v1.1.2" in 39.692700375s
Normal Created 20m kubelet Created container install-cni-plugin
Normal Started 20m kubelet Started container install-cni-plugin
Warning Failed 97s kubelet Failed to pull image "docker.io/flannel/flannel:v0.21.5": rpc error: code = Unknown desc = context canceled
Warning Failed 97s kubelet Error: ErrImagePull
Normal BackOff 96s kubelet Back-off pulling image "docker.io/flannel/flannel:v0.21.5"
Warning Failed 96s kubelet Error: ImagePullBackOff
Normal Pulling 84s (x2 over 20m) kubelet Pulling image "docker.io/flannel/flannel:v0.21.5"
可以看出上面在拉取镜像docker.io/flannel/flannel:v0.21.5
的时候出了问题。那就手动帮它一下:
docker pull docker.io/flannel/flannel:v0.21.5
等待镜像pull完成,再次kubectl apply -f kube-flannel.yml
再次查看pod和nodes状态:
root@ubuntu:~# kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-pj5pn 1/1 Running 0 37m
...
root@ubuntu:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
ubuntu Ready control-plane,master 46m v1.21.2
现在已经Ready了。