kubeadm使用docker和flannel创建k8s三节点集群

首发: xiaojueguan的IT世界

环境介绍

root@k8s1:~# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:37:34Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"
root@k8s1:~# docker --version
Docker version 20.10.8, build 3967b7d
root@k8s1:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.2 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

前言

由于Kubernetes的官方镜像都在k8s.gcr.io/v2/, 所以我们直接拉取的话会有网络连通性的问题,从而出现类似下面的报错

[preflight] Some fatal errors occurred:
	[ERROR ImagePull]: failed to pull image k8s.gcr.io/etcd:3.5.0-0: output: Error response from daemon: Get "https://k8s.gcr.io/v2/": context deadline exceeded
, error: exit status 1
	[ERROR ImagePull]: failed to pull image k8s.gcr.io/coredns/coredns:v1.8.4: output: Error response from daemon: Get "https://k8s.gcr.io/v2/": context deadline exceeded
, error: exit status 1

对于这个问题,我们的解决方式有三种:

  1. 使用proxy
  2. 换一个镜像源拉取镜像到本地然后将镜像改名为k8s.gcr.io开头的
  3. 自己创建一个镜像仓库, 然后在kubeadm init的时候加上参数例如--image-repository=k8s.xiaojueguan.io

本文会介绍下使用proxy的方式:
主要在两个地方会用到proxy:

  1. apt的proxy用于安装kubelet,kubeadm,kubectl
  2. docker的proxy用户

在解决完k8s部署主要使用的软件和镜像后我们还需要做出如下选择

  1. 容器运行时(container runtime)
    • containerd
    • CRI-O
    • Docker
  2. 容器网络接口(container network interface)
    • ACI
    • Antrea
    • AWS VPC CNI for Kubernetes
    • Azure CNI for Kubernetes
    • Calico
    • Cilium
    • CNI-Genie from Huawei
    • cni-ipvlan-vpc-k8s
    • Coil
    • Contiv
    • Contrail / Tungsten Fabric
    • DANM
    • Flannel
    • Google Compute Engine (GCE)
    • Jaguar
    • k-vswitch
    • Knitter
    • Kube-OVN
    • Kube-router
    • L2 networks and linux bridging
    • Multus (a Multi Network plugin)
    • OVN4NFV-K8s-Plugin (OVN based CNI controller & plugin)
    • NSX-T
    • Nuage Networks VCS (Virtualized Cloud Services)
    • OpenVSwitch
    • OVN (Open Virtual Networking)
    • Romana
    • Weave Net from Weaveworks

这里我们选用docker作为host runtime,选择flannel作为CNI.

安装docker

  1. 安装设置使用https的仓库需要的包
sudo apt-get update && sudo apt-get install -y \
  apt-transport-https ca-certificates curl software-properties-common gnupg2
  1. 添加docker官方的GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key --keyring /etc/apt/trusted.gpg.d/docker.gpg add -
  1. 添加docker 的 apt 仓库
sudo add-apt-repository \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) \
  stable"

4 安装docker ce

sudo apt-get update && sudo apt-get install -y \
  containerd.io \
  docker-ce \
  docker-ce-cli

5 设置docker代理

mkdir -p /etc/systemd/system/docker.service.d
cat << EOF > /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://10.10.1.190:1080"
Environment="HTTPS_PROXY=http://10.10.1.190:1080"
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,.corp,10.10.1.0/24"
EOF
  1. 设置docker的cgroup驱动为systemd
cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF
  1. 重启Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
  1. 设置docker自启动
sudo systemctl enable docker

使用部署工具安装kubernetes

确认mac地址和product_uuid在每个节点上都不同。你可以通过ip link或者ifconfig -a来获取网卡的地址。
你可以通过sudo cat /sys/class/dmi/id/product_uuid获取product_uuid, 通常硬件设备是拥有不同的地址,但是一些虚拟机可能拥有相同的标识值。kubernetes使用这些值来标识集群中的节点。如果这些值相同的话,安装过程中会报错。
检查你的网卡,确保你各个节点的网卡可以相通。
让网桥上的流量对iptables可见。你可以通过lsmod | grep br_netfilter验证,通过sudo modprobe br_netfilter来加载br_netfilter模块。此外为了保证你的linux节点上的iptables可以正确看到桥上的流量可以进行如下操作:
通过下面命令来查看br_netfilteroverlay是否已经加载了,如果没有加载的话通过下面的命令加载:

cat <<EOF | sudo tee /etc/modules-load.d/crio.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

通过下面的设置使iptables可以查看到桥上的流量

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

设置apt代理

cat <<EOF > /etc/apt/apt.conf.d/proxy.conf
Acquire {
  HTTP::proxy "http://10.10.1.190:1080";
  HTTPS::proxy "http://10.10.1.190:1080";
}
EOF

安装kubeadm, kubelet and kubectl

sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

禁用swap

swapoff -a

用kubeadm初始化一个集群

通过下面的命令来设置第一个node

kubeadm init \
--apiserver-advertise-address=10.10.1.211 \
--kubernetes-version=v1.22.2  \
--pod-network-cidr=10.244.0.0/16 -v=9

跑完后便会看到如下的结果

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 10.10.1.211:6443 --token i978xo.oiu48b2pimdig1xl \
	--discovery-token-ca-cert-hash sha256:365c9d9408404a228e66159adef8513752b04bd2be3f5afc3ce4354a96aa04e2

但是这个时候我们我们通过下面的命令会看到两个coredns的pod处于0/1的状态

export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl get pod -n kube-system

这个时候我们需要设置cni,这里我们使用flannedl
获取kube-flannel.yml文件

wget kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

使用你的编辑器查看kube-flannel.yml,确保如下配置中的Network字段是和你上面的pod-network-cidr是一样的

  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }

建立flannel

export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f kube-flannel.yml

如果遇到问题可以查看下面的tips

此时我们可以观察到所有的coredn的pod都起来了,然后参考上文在其他节点上

  1. 安装docker
  2. 加载mod
  3. 设置系统参数
  4. 关闭swap
  5. 安装kubeadm和kubelet
    最后执行类似下面的命令让新的node加入到集群
kubeadm join 10.10.1.211:6443 --token i978xo.oiu48b2pimdig1xl \
	--discovery-token-ca-cert-hash sha256:365c9d9408404a228e66159adef8513752b04bd2be3f5afc3ce4354a96aa04e2

配置kubelet自动补全

  1. 配置kubelet completion
    安装bash-completion如果安装了可以跳过这一步
# ubuntu, Debian, Hypriotos
apt-get install bash-completion

# Centos,RHEL or Fedora
yum install bash-completion

可以使用下面两种方式开启kubelet自动补全

  • 将补全的script加到~/.bashrc
echo 'source <(kubectl completion bash)' >>~/.bashrc
  • 将补全的script加到/etc/bash_completion.d/kubectl这个文件中
kubectl completion bash >/etc/bash_completion.d/kubectl

如果使用了alias的话可以使用下面的命令进行配置

echo 'alias k=kubectl' >>~/.bashrc
echo 'complete -F __start_kubectl k' >>~/.bashrc

Tips

  1. 如果初始化被打断可以通过下面的命令reset节点
kubeadm reset
rm -fr ~/.kube
  1. 如果容器没有被拉起来
    大概率的kubelet服务不正常,如果不正常根据日志里面的报错具体问题分析
systemct status kubelet
journalctl -f -u kubelet
  1. 如果coredns没起来
    多半是你设置cni的网络和你init时指定的不一样.

问题

  1. 只在节点以上安装了cni是不是其他节点上就没有cni了?
  2. pod之间的网络是怎么走的?

参考

Install and Set Up kubectl | Kubernetes
使用kubeadm 安装k8s_ふりこ细工の心-CSDN博客
Control Docker with systemd | Docker Documentation

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐