关键词:ubuntu, k8s

ubuntu 下安装 k8s

安装 k8s 准备工作

准备工作

我们先假设以下的情况成立。

机器:有2-3台物理机或虚拟机 系统:Ubuntu 18.04 以上且已换好国内的源 如果以上基本不成立,本篇文章到此结束,谢谢观看…

安装Docker

我也不需要介绍各种情况了,直接登上机器,创建一个shell脚本,例如叫install_docker.sh,一把梭代码如下。

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates 
curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io

然后执行sh install_docker.sh,等待命令跑完,验证docker是否安装好即可。直接敲docker + 回车。

安装Kubernetes

同理,新建一个shell脚本,例如install_k8s.sh。一把梭代码如下。

sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get install -y kubelet kubeadm kubectl --allow-unauthenticated

需要注意的是, sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - 可能会失败,因为墙的原因,因此,我们需要在可以下载到的地方提前下载好,然后 scp 到机器,然后使用 sudo apt-key add apt-key.gpg 即可。

另外安装时还有连不上的情况, 换国内的源

sudo apt-get update
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial main
EOF
sudo apt-get install -y kubelet kubeadm kubectl --allow-unauthenticated

然后执行sh install_k8s.sh,等待命令跑完,验证k8s是否安装好即可。直接敲kubectl + 回车。

关闭Swap

先给出一把梭,不要耽误了正在安装的老铁。为什么要关闭后面再说。

暂时关闭 直接使用命令 sudo swapoff -a,但是重启之后会生效。会导致 k8s 无法正常运行。 永久关闭 建议一劳永逸,sudo vim /etc/fstab 将有 swap.img 那行注释掉,保存即可。

那么,swap是啥呢?它是系统的交换分区,你可以理解为虚拟内存。当系统内存不足的时候,会将一部分硬盘空间虚拟成内存使用。

初始化Master节点

到这,准备工作就完成了,可以开始安装K8S的master节点了,登上要作为 master 节点的机器。

设置HostName

老规矩,先上命令,再说为什么要设置。

sudo hostnamectl set-hostname master-node

自定义修改了主机名,在之后查看集群内节点时,每个节点的名字就不会显示K8S自动生成的名字,便于查看和记忆。例如,在其他的 Node 节点你可以将 master-node 改为 slave-node-1 或worker-node-2

Master 节点配置 cgroup driver

方法一

修改 kubelet 配置 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
CPUAccounting=true
MemoryAccounting=true
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --cgroup-driver=systemd"  #配置在这里cgroup-driver=systemd
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/sysconfig/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

方法二

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

初始化 master 节点

初始化过程会访问墙外网站,如果 init 不能顺利执行,请配置全局代理或者用下面的脚本提前跑好:

#!/bin/bash

images=(
kube-apiserver:v1.20.1
kube-controller-manager:v1.20.1
kube-scheduler:v1.20.1
kube-proxy:v1.20.1
pause:3.2
etcd:3.4.13-0
coredns:1.7.0
)

for imageName in ${images[@]} ; do
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
    docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
done

然后执行

sudo kubeadm init --apiserver-advertise-address=192.168.56.200 --pod-network-cidr=10.244.0.0/16

  • apiserver-advertise-address=192.168.56.200 绑定 apiserver 到 master 节点的 Host-Only 适配器的地址,默认是绑到 NAT 的地址上,这样其他机器是永远也访问不到的。

  • pod-network-cidr=10.244.0.0/16 指定 pod 网络地址空间,我们使用 flannel 组件必须使用这个空间。

kubeadm 的完整参考手册 kubeadm reference guide

推荐保存最后输出的 join 命令到文件(以免忘记或找不到了),方便添加节点到集群。如果忘了也找不到输出了,网上有方法生成哈希值,请自行查找。

这里碰到的问题是第一次因为 docker cgroup 的原因失败了,因此又重新执行,导致了如下错误,解决办法也在下面了:

[init] Using Kubernetes version: v1.20.1
[preflight] Running pre-flight checks
	[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.1. Latest validated version: 19.03
error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
	[ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
	[ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
	[ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
	[ERROR Port-10250]: Port 10250 is in use
	[ERROR DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

解决方法: use "kubeadm reset" and reinitialize the kubeadm using "kubeadm init"

地址: https://github.com/kubernetes/kubeadm/issues/1616

配置 kubectl 访问集群

# non-root user
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

测试配置

kubectl cluster-info # 有正常输出即可

安装 flannel 网络

安装与配置

flannel 默认的监听接口是 NAT 适配器的接口,我们需要的是 Host-Only 适配器的接口,所以需要修改 kube-flannel.yml 文件

# 这个值金额搞好像 也是下载不了的,还是需要复制他
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

给 /opt/bin/flanneld 命令添加 –iface=“enp0s8” 参数 # enp0s8 是 Host-Only 适配器对应的接口

kubectl apply -f kube-flannel.yml

测试是否 OK

kubectl get pods --all-nam espaces -o wide # 稍等一会,下载镜像需要一定时间,�最后应该显示 flannel pods 是 Running 状态, kube-dns 也是 Running 状态

增加其他节点

在节点上执行 kubeadm init 最后输出的 join 命令

kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>

一旦遇到状态是 notReady 的情况大概率是拉镜像被强了,因此需要在 node 机器上使用脚本提前把镜像拉好,脚本在本文的上面。

然后在 master 节点如下做:

fupeng@master-node:~$ kubectl get node
NAME             STATUS   ROLES                  AGE   VERSION
master-node      Ready    control-plane,master   11m   v1.20.1
worker-node-03   Ready    <none>                 21s   v1.20.1
fupeng@master-node:~$ kubectl get pods --all-namespaces -o wide
NAMESPACE     NAME                                  READY   STATUS    RESTARTS   AGE     IP           NODE             NOMINATED NODE   READINESS GATES
kube-system   coredns-74ff55c5b-lfjxj               1/1     Running   0          11m     10.244.0.3   master-node      <none>           <none>
kube-system   coredns-74ff55c5b-mkn4h               1/1     Running   0          11m     10.244.0.2   master-node      <none>           <none>
kube-system   etcd-master-node                      1/1     Running   0          11m     10.0.2.15    master-node      <none>           <none>
kube-system   kube-apiserver-master-node            1/1     Running   0          11m     10.0.2.15    master-node      <none>           <none>
kube-system   kube-controller-manager-master-node   1/1     Running   0          11m     10.0.2.15    master-node      <none>           <none>
kube-system   kube-flannel-ds-9hmr5                 1/1     Running   0          23s     10.0.2.15    worker-node-03   <none>           <none>
kube-system   kube-flannel-ds-v4vft                 1/1     Running   0          4m37s   10.0.2.15    master-node      <none>           <none>
kube-system   kube-proxy-2trdt                      1/1     Running   0          11m     10.0.2.15    master-node      <none>           <none>
kube-system   kube-proxy-z5bgv                      1/1     Running   0          23s     10.0.2.15    worker-node-03   <none>           <none>
kube-system   kube-scheduler-master-node            1/1     Running   0          11m     10.0.2.15    master-node      <none>           <none>

参考:


  1. 如果不是ready状态, 查看日志, 看原因

journalctl -f -u kubelet.service

  1. 如果任一 Pod 状态不为 Running,请运行以下命令:

$ kubectl describe pod yourPodName -n kube-system

  1. 为了从 aws-node 和 kube-proxy Pod 日志中获取其他信息,请运行以下命令:

$ kubectl logs yourPodName -n kube-system

  1. 在node上执行kubeadm reset 可以断开node, 然后重新join
  2. 在master上执行kubeadm reset后可以重新init