三节点k8s集群的构建

三节点k8s集群的构建

前言

咕了要一年的文章哈,一开始老想着在家用自己刷了linux的笔记本+另外两台机器的wsl搭建集群,但是麻烦事太多了。 最终选择了公司的云平台搞三台虚拟机来练手

相较于 单节点的k8s安装,多节点的最大的不同是需要CNI来进行组网

这里笔者选用了cilium

步骤规划:

  1. 部署管理面平台
  2. 载入CNI
  3. 部署work节点

使用系统: Ubuntu 20.04

如果想要寻找快速搭配的命令,可以直接看 work节点的一图流,然后使用master的 部署k8s-master 与 cilium

部署管理面平台

基础环境准备

这里的安装在过去的文章有提及,就不重复了 PS: 在后续走到了 1.24的安装后突然想起来,1.24开始 k8s 不在默认支持docker Engine作为CRI,后文将会有container的安装过程

单节点k8s环境搭建

ubuntu 的 swap 禁用

sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
sudo swapoff -a

如果不禁用,在后续的kubeadm 会出现 kubelet-check] Initial timeout of 40s passed.

这里遇到了一个意料之外的问题

ProxyChains-3.1 (http://proxychains.sf.net)
|DNS-response|: ubuntu-vm does not exist
|DNS-response|: ubuntu-vm does not exist
sudo: unable to resolve host ubuntu-vm: Unknown error

找了几种方法,比如 安装 reslove tor

最后发现了一个奇怪的解决方法

mkdir /etc/apt/keyrings/
proxychains curl -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

或者用另一个解法,不要用sudo 不用sudo就好了= =

但是有一个新的问题 apt-get updat 的时候

Err:7 https://packages.cloud.google.com/apt kubernetes-xenial Release
  404  Not Found [IP: 142.250.194.238 443]

直接访问了这个 url 也是404 所以这里 仓库配置就不使用 google的仓库了,使用阿里云的

curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main"

google 仓库404问题的补充

根据 问答 该问题的评论,这是一个已知问题

解决方案是获取最新的密钥:

// 但是看上去其实没区别 应该是无效的,等到我work节点的时候试试不用 google 的 可不可行

curl  https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/google-keyring.gpg 
echo "deb [signed-by=/usr/share/keyrings/google-keyring.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

安装的版本用新一些的

apt install -y kubelet=1.24.17-00 kubeadm=1.24.17-00 kubectl=1.24.17-00
apt-mark hold kubelet kubeadm kubectl

containerd 安装

安装 containerd 可以直接使用 apt-get apt-get install containerd containerd.io -y

按照文档描述,通过apt-get安装的containerd.io 包含了runc,但是并不包含 CNI 插件。

后续这里可能会带来一个坑。 不过目前就是走一步看一步

这样安装的后 /etc/containerd/config.toml 的配置文件可能不全

可以考虑手动初始化配置

sudo rm -rf /etc/containerd/config.toml
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd

安装后可以使用 ctr -v 得到输出,但是这个玩意很不好用,需要再安装客户端工具

常见的推荐就是 crictl与nerdctl 笔者这里使用 crictl

直接使用官方文档给的方式

VERSION="v1.28.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz

安装完后尝试使用 crictl ps 之类的会返回错误,因为默认使用的还是 /var/run/dockershim.sock

  • 如果执行了手动初始化,这一步可以跳过*
  • 建议执行,因为可能没有默认的配置文件,导致运行出现无意义报错*
validate service connection: validate CRI v1 image API for endpoint "unix:///var/run/dockershim.sock": rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial unix /var/run/dockershim.sock: connect: no such file or directory"
cat >> /etc/crictl.yaml << EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 3
debug: true
EOF

之后会发现还是无法使用,因为需要再调整containerd 的配置 vim /etc/containerd/config.toml

注释 disabled_plugins = ["cri"]

然后重启 containerd

systemctl restart containerd

就可以了

配置 cgroup 驱动为 systemd

在 /etc/containerd/config.toml 中设置

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
export PAUSE_IMAGE="$(kubeadm config images list | grep pause)"
sudo sed -i 's,sandbox_image = .*,sandbox_image = '\"$PAUSE_IMAGE\"',' /etc/containerd/config.toml

启用cri插件 sudo sed -i 's/^disabled_plugins \=/\#disabled_plugins \=/g' /etc/containerd/config.toml

安装 cni插件

sudo mkdir -p /opt/cni/bin/
sudo wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.3.0.tgz

修改hostname 因为这里的环境使用的是云平台统一创建的虚拟机,所以三台虚拟机的hostname相同,这里做一下修改 hostnamectl set-hostname y1nhui-k8s-master

参考 cilium 的官方文档。我们在执行完k8s master 节点的部署后再执行 CNI 的相关安装

  • 很重要,如果不改,哪怕下面的行为已经拖了镜像到本地,apiserver 也会无法启动*

再补充一个 更改 containerd 的 registry

sed -i 's/registry.k8s.io/registry.aliyuncs.com\/google_containers/' /etc/containerd/config.toml
systemctl daemon-reload
systemctl restart containerd

配置 iptables

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

sudo modprobe overlay
sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

部署 k8s-master

配置 kubeadm的推荐方式时通过 –config 传递

自定义镜像仓库

考虑到网络问题,这里需要使用 如 阿里云之类的 镜像仓库

导出 kubeadm 默认 init 配置 kubeadm config print init-defaults > init.conf

做 如下修改

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: 10.10.88.177 # 对外公开地址
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  name: k8s-master # 节点名称 不配置的话则为节点主机名
  taints: null # 污点配置,未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.cn-hangzhou.aliyuncs.com/google_containers #registry.k8s.io 替换为国内镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.24.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 10.244.0.0/16 #  pod 使用的 CIDR
scheduler: {}
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

先 pull 镜像看看是否有问题

kubeadm config images pull --config init.yaml

之后执行 kubeadm init --config=init.yaml --upload-certs --skip-phases=addon/kube-proxy --v=5

  • skip-phases=addon/kube-proxy 为 cilium 官方要求,若使用CNI不是cilium请参考对应文档
  • upload-certs 官网描述为 上传管理面证书到kubeadm-certs Secret 意义不明,但是查找资料有文档推荐使用

执行之后便可以见到成功输出

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:

并且执行提示的指令

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

cilium 部署

安装 helm

查看官方文档与各种其他资料,似乎并不能绕开helm。所以需要先安装一个helm

proxychains wget https://get.helm.sh/helm-v3.12.3-linux-amd64.tar.gz

tar -zxvf helm-v3.12.3-linux-amd64.tar.gz && mv linux-amd64/helm /usr/local/bin/helm

安装 cilium

添加repo

helm repo add cilium https://helm.cilium.io/

安装 cilium 注意这里需要设置 ip port, 直接使用安装会导致cilium无法启动

API_SERVER_IP=<your_api_server_ip>
# Kubeadm default is 6443
API_SERVER_PORT=<your_api_server_port>
proxychains helm install cilium cilium/cilium --version 1.15.5 \
    --namespace kube-system \
    --set kubeProxyReplacement=true \
    --set k8sServiceHost=${API_SERVER_IP} \
    --set k8sServicePort=${API_SERVER_PORT}

安装 cilium cli 验证安装

wget https://github.com/cilium/cilium-cli/releases/download/v0.16.7/cilium-linux-amd64.tar.gz
tar xzvfC cilium-linux-amd64.tar.gz  /usr/local/bin
rm cilium-linux-amd64.tar.gz

使用 cilium status –wait 查看

发现 Deployment cilium-operator Desired: 2, Ready: 1/2, Available: 1/2, Unavailable: 1/2

但是 通过 kubectl get node 可见 node 已经处于ready(因为kubeadm安装跳过了 kube-proxy,所以如果没有安装cilium等 cni,node 将会处于no ready)

部署 work

总结出可以直接使用的命令流程,可能又部分需要加proxychains 但是直接走到底可以做到一切正常

work 准备工作执行指令一图流

sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
sudo swapoff -a
sudo apt-get update
sudo install -m 0755 -d /etc/apt/keyrings
sudo apt-get install -y apt-transport-https ca-certificates curl
proxychains curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main"
curl  https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/google-keyring.gpg 
echo "deb [signed-by=/usr/share/keyrings/google-keyring.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt install -y kubelet=1.24.17-00 kubeadm=1.24.17-00 kubectl=1.24.17-00
apt-mark hold kubelet kubeadm kubectl

proxychains curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo rm -rf /etc/containerd/config.toml
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl stop docker
sudo systemctl restart containerd

VERSION="v1.28.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
export PAUSE_IMAGE="$(kubeadm config images list | grep pause)"
sudo sed -i 's,sandbox_image = .*,sandbox_image = '\"$PAUSE_IMAGE\"',' /etc/containerd/config.toml

sudo mkdir -p /opt/cni/bin/
sudo wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.3.0.tgz

hostnamectl set-hostname y1nhui-k8s-work1

sed -i 's/registry.k8s.io/registry.aliyuncs.com\/google_containers/' /etc/containerd/config.toml
systemctl daemon-reload
systemctl restart containerd

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

sudo modprobe overlay
sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

因为 containerd.io 通过 docker 分发,所以通过apt 安装 containerd 需要 docker 的仓库

同时需要安装docker-ce等,否则会遇到

The following packages have unmet dependencies:
 containerd.io : Conflicts: containerd
E: Unable to correct problems, you have held broken packages.

加入集群

首先在 master节点创建token

kubeadm token create

返回的内容类似

5didvk.d09sbcov8ph2amjw

使用命令获取 ca-cert-hase openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \ openssl dgst -sha256 -hex | sed 's/^.* //'

返回类似

8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78

使用kubeadm join 命令加入

kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>n

比如笔者的这里使用

kubeadm join 10.10.88.177:6443 --token y76ltj.xyqwukvkuax0xa9b --discovery-token-ca-cert-hash sha256:4e872afb456e0f05ba34ec0c381895b189b6f5cbd27ffcc1c6afdab0931ca026 --node-name k8s-work1

或许读者会发现有的资料提及到了 使用带配置文件的 join,但是考虑到官方文档表示该功能为beta功能,未来可能变动,所以不使用

执行之后,在master使用 kubectl get node 可以见到返回如下

NAME         STATUS     ROLES           AGE   VERSION
k8s-master   Ready      control-plane   52d   v1.24.17
k8s-work1    NotReady   <none>          10s   v1.24.17

等待cilium 加载后,work1 变回ready

可选

配置 containerd 代理

创建 containerd service 文档

mkdir /etc/systemd/system/containerd.service.d/

写入代理

cat > /etc/systemd/system/containerd.service.d/http-proxy.conf <<-EOF
[Service]
Environment="HTTP_PROXY=<your_proxy>"
Environment="HTTPS_PROXY=<your_proxy>"
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.cluster.local,.ewhisper.cn,<nodeCIDR>,<APIServerInternalURL>,<serviceNetworkCIDRs>,<etcdDiscoveryDomain>,<clusterNetworkCIDRs>,<platformSpecific>,<REST_OF_CUSTOM_EXCEPTIONS>"
EOF

重启

systemctl daemon-reload
systemctl restart containerd

安装 hubble

获取 hubble yaml

proxychains wget https://raw.githubusercontent.com/cilium/hubble/v0.5/tutorials/deploy-hubble-servicemap/hubble-all-minikube.yaml

创建pod等

kubectl apply -f hubble-all-minikube.yaml

创建一个 nodeport

kubectl -n kube-system get svc hubble-ui -o yaml > ui.yaml

修改 type 为 NodePort,sepc 只保留 ports selector sessionAffinity 与 type

启用后,即可通过nodeport 访问 hubble 网页

总结

本文总结了无kube-proxy安装 使用 cilium的 k8s集群

文章写作一拖再拖,终于实在看了玩k8s in action 打算开始学 service mesh 没有环境忍无可忍的情况下写完