Ubuntu20.04部署k8s


简介

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机制:cgroupfssystemd,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了。


文章作者: Wyx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wyx !
  目录