2022-11-15Kubernetes0
请注意,本文编写于 194 天前,最后修改于 192 天前,其中某些信息可能已经过时。

目录

Kubernetes 最小的集群应该是 Control Plane Node 1 + Worker Node 2
1.禁止 swap 分区
2. 更新机器的 hostname
3. 修改 IP 和设置 dns 服务器
安装运行时
安装 docker
安装 cri-docker 服务
1. 直接下载安装包
2. 从源码编译而后进行安装
安装 kubelet/kubeadm/kubectl 核心组件
复制了 2 台 worker node 之后
初始化 control plane
docker 设置代理
设置集群内网组件
检查 control plane 是否 ready
增加 worker
设置 load balancer 组件
Q & A

文本主要内容

  1. Hyper-V 复制虚拟机,快速拓展集群
  2. Kubernetes 的最小集群创建
  3. 使用 Metallb 作为外部的负载均衡器
  4. 使用 pihole 作为私有域名解析服务器

Kubernetes 最小的集群应该是 Control Plane Node * 1 + Worker Node *2

按照最小集群的要求,我们需要 3 台一模一样的空白的 Linux 虚拟机做好准备,然后选择其中一台作为 Control Plane

上述步骤完成之后只是创建了一台 Ubuntu 的虚拟机它具备了如下特性:

  • 干净整洁的预备役环境
  • 固定的 IP (这个十分重要)
  • 你通过本机的 ssh 可以直连它

因此,接下来你要做的是给它安装 Kubernetes 所需要的组件,然后用 Hyper-V 自带的虚拟机复制功能,复制 2 台 Linux Server 当作 Worker Node

在复制虚拟机之前,我们还需要进行一些准备工作

1.禁止 swap 分区

$ sudo swapoff -a
$ sudo rm /swap.img

2. 更新机器的 hostname

$ sudo vi /etc/hostname

把 hostname 改成 kube-master

再修改 hosts

$ sudo vi /etc/hosts

改成如下内容

127.0.0.1 localhost
127.0.1.1 kube-master

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

这里必须重启一次

$ sudo reboot # 这里必须重启第一次

3. 修改 IP 和设置 dns 服务器

$ sudo vi /etc/netplan/00-installer-config.yaml 

把内容换成以下:

yaml
# This is the network config written by 'subiquity'
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses:
        - 192.168.137.100/24
      nameservers:
        addresses: [192.168.137.1] # 这个是 Windows 宿主机在当前虚拟交换机下的 IP
      routes:
        - to: default
          via: 192.168.137.1

如此设置是为了让虚拟机能够依赖宿主机访问外网和 dns 解析。

注意1

这里需要格外的几点:
192.168.137.1: 这个 IP 是你之前设置 内网交换机时,Windows 宿主机在这个内网下的 IP

在 Windows 找到网络设置,如下图

image.png

注意2

192.168.137.100/24 : 这个 IP 是你当前虚拟机的 IP

在 Linux 虚拟机执行:

$ ip r

如下图

image.png

至此,第一步网络设置基本完成,接下来我们要安装 kubernetes 的运行时

安装运行时

注意

这里我选用了 docker 作为容器运行时,其实现在 Kubernetes 官方已经不推荐了,只是我已经习惯了 docker,因此我选用它

安装 docker

$ sudo apt-get update
$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
$ sudo groupadd docker
$ sudo usermod -aG docker $USER

执行上面的命令之后再次重启

$ sudo reboot # 这里必须第二次重启

安装 cri-docker 服务

https://github.com/Mirantis/cri-dockerd 项目是专门解决 docker 不遵循 kubernetes 标准容器协议问题而开发的组件,使得 kubernetes 能够和 docker 协作

这里有两种方法安装 cri-docker

1. 直接下载安装包

打开 releases 界面https://github.com/Mirantis/cri-dockerd/releases 找到 cri-dockerd_0.2.6.3-0.ubuntu-jammy_amd64.deb
(注意版本号,找到 ubuntu-xxx_amd64.deb 的版本即可)

shell
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.6/cri-dockerd_0.2.6.3-0.ubuntu-jammy_amd64.deb
# 如果你宿主机有代理则可以如下
# curl -L https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.6/cri-dockerd_0.2.6.3-0.ubuntu-jammy_amd64.deb --proxy "http://192.168.137.1:7890"  --output cri-dockerd_0.2.6.3-0.ubuntu-jammy_amd64.deb

安装

shell
$ sudo apt install ./cri-dockerd_0.2.6.3-0.ubuntu-jammy_amd64.deb
shell
$ sudo reboot

2. 从源码编译而后进行安装

官方教程里面建议你从源码进行编译,这里对大陆用户有一个难点就是编译的时候需要下载最新版本的 go 语言的编译器和运行时,所以我这里推荐你可以从 apt install 先安装 go 语言的环境:

shell
$ sudo apt intsall golang-go

执行 sudo -s 获取 root 权限

shell
$ git clone https://github.com/Mirantis/cri-dockerd.git
$ cd cri-dockerd
$ mkdir bin
$ go build -o bin/cri-dockerd
$ mkdir -p /usr/local/bin
$ install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
$ cp -a packaging/systemd/* /etc/systemd/system sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
$ systemctl daemon-reload
$ systemctl enable cri-docker.service
$ systemctl enable --now cri-docker.socket

以上两种方式均可,安装完成之后校验服务运行状态:

shell
$ sudo systemctl status docker
$ sudo systemctl status cri-docker
shell
[email protected]:~$ systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-11-08 08:12:00 UTC; 1min 54s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 759 (dockerd)
      Tasks: 81
     Memory: 51.0M
        CPU: 1.176s
     CGroup: /system.slice/docker.service
             ├─ 759 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

[email protected]:~$ systemctl status cri-docker
● cri-docker.service - CRI Interface for Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/cri-docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-11-08 08:12:00 UTC; 1min 59s ago
TriggeredBy: ● cri-docker.socket
       Docs: https://docs.mirantis.com
   Main PID: 1715 (cri-dockerd)
      Tasks: 7
     Memory: 11.2M
        CPU: 78ms
     CGroup: /system.slice/cri-docker.service
             └─1715 /usr/bin/cri-dockerd --container-runtime-endpoint fd://
lines 1-11...skipping...
● cri-docker.service - CRI Interface for Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/cri-docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-11-08 08:12:00 UTC; 1min 59s ago
TriggeredBy: ● cri-docker.socket
       Docs: https://docs.mirantis.com
   Main PID: 1715 (cri-dockerd)
      Tasks: 7
     Memory: 11.2M
        CPU: 78ms
     CGroup: /system.slice/cri-docker.service
             └─1715 /usr/bin/cri-dockerd --container-runtime-endpoint fd://

安装 kubelet/kubeadm/kubectl 核心组件

这里我建议尽量在你宿主机 Windows 安装一个梯子,保证你能链接到 google 服务器:

假设你在 Windows 宿主机上有一个梯子监听的是 7890 端口 那么你在 Linux 虚拟机内部执行 apt 命令的时候都可以加一个参数让 Linux 虚拟机都可以享受到你宿主机梯子的便利

shell
$ sudo apt install --option Acquire::HTTP::Proxy="http://192.168.137.1:7890"

注意

如下的命令行在执行 apt-get | update | install 的时候请一定记得加上如上的代理参数

shell
$ sudo apt-get update
$ sudo apt-get install -y apt-transport-https ca-certificates curl
$ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
$ 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

注意

至此一台完全准备好的 Kubernetes Node 服务器已经就绪,它即可以作为 Control Plane 也可以作为 Worker Node

接下来要使用 Hyper-V 复制出 2 台机器,用来组成 Control Plane ✖ 1 + Worker Node ✖ 2 的最小集群
这里推荐阅读微软官方文档->https://learn.microsoft.com/zh-cn/windows-server/virtualization/hyper-v/deploy/export-and-import-virtual-machines

复制了 2 台 worker node 之后

  1. 要修改他们的 hostname,复制的虚拟机会使用原来的 kube-master,请分别改为 kube-worker-2 和 kube-worker-2
$ sudo vi /etc/hostname

把 hostname 改成 kube-worker-1(第二台改成 kube-worker-2)

再修改 hosts

$ sudo vi /etc/hosts

改成如下内容

127.0.0.1 localhost
127.0.1.1 kube-worker-1 

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

(第二台改成 127.0.1.1 kube-worker-2)

$ sudo reboot # 这里必须重启第一次
  1. 修改 IP 和设置 dns 服务器
shell
$ sudo vi /etc/netplan/00-installer-config.yaml 
yaml
# This is the network config written by 'subiquity'
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses:
        - 192.168.137.101/24
      nameservers:
        addresses: [192.168.137.1]
      routes:
        - to: default
          via: 192.168.137.1

kube-worker-1 的 IP 改为 192.168.137.101/24
kube-worker-2 的 IP 改为 192.168.137.102/24

两台机器再次分别重启

shell
$ sudo reboot # 这里必须重启第一次

初始化 control plane

要执行初始化集群,中国区的用户在这一步会卡住,因为 kubenetes 的官方镜像是存储在 google 的自己的服务器上的,因为众所周知的原因,我们有如下 2 个方案解决:

  1. 给你的 docker 设置一个代理服务器,当然这台代理服务器得是一台“佛跳墙”服务器 - -!

docker 设置代理

shell
$ sudo vi /lib/systemd/system/docker.service

将 [Service] 的内容添加如下几行:

yaml
Environment="HTTP_PROXY=http://192.168.137.1:7890"
Environment="HTTPS_PROXY=http://192.168.137.1:7890"
Environment="NO_PROXY=127.0.0.0/8,172.17.0.0/16"

然后重启 docker 服务

shell
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker.service
  1. 修改你 docker pull 的 mirror 为国内的源
shell
$ sudo -s
$ kubeadm init --cri-socket=unix:///var/run/cri-dockerd.sock --apiserver-advertise-address=192.168.137.100 --pod-network-cidr=10.244.0.0/16

安装成功之后,启用 kubectl

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

设置集群内网组件

官方文档 -> https://github.com/flannel-io/flannel

shell
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

检查 control plane 是否 ready

shell
$ kubectl get nodes
shell
$ [email protected]:~$ kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
kube-master   Ready    control-plane   10m   v1.25.3

增加 worker

来到 worker-1 机器内

加入刚才创建的集群,如果你刚刚创建完集群,它会打印 kubeadm join 的命令行,让你在 worker node 上加入到集群,如果你超过了 1 天再来加入集群需要重新获取 token,在 control plane 节点上执行:

shell
$ kubeadm token list

会得到如下输出

output
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
os00ln.sgr4pcrvpzlehze0   20h         2022-11-16T11:50:52Z   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token

然后获取一下获取 ca 证书 sha256 编码 hash 值

shell
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
output
162e0ea67395442de0a5eeeeaa0a6bf0b0e8f543e557a05cdab68af8363500b2

再回到你要加入集群的 worker node 上执行如下:

shell
$ sudo -s
$ kubeadm join 192.168.137.100:6443 --token os00ln.sgr4pcrvpzlehze0 \
        --discovery-token-ca-cert-hash sha256:162e0ea67395442de0a5eeeeaa0a6bf0b0e8f543e557a05cdab68af8363500b2 \
        --cri-socket=unix:///var/run/cri-dockerd.sock

短暂的几秒之后,你就可以执行

shell
$ kubectl get nodes

查看节点是否已经成功加入并且准备就绪。

设置 load balancer 组件

官方文档 -> https://metallb.universe.tf/installation/

shell
$ kubectl edit configmap -n kube-system kube-proxy

修改关键内容:

yaml
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true

然后安装

shell
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml

设置 IP pool 的范围,这里十分重要

创建文件 metallb-config.yaml

yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.137.120-192.168.137.180
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: use-eth0
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool
  interfaces:
  - eth0  

需要格外注意的配置项是:

yaml
  addresses:
  - 192.168.137.120-192.168.137.180

这个配置必须跟你宿主机以及你 3 台集群的 IP 都在一个子网段内

以及

yaml
  interfaces:
  - eth0  

必须跟你虚拟机的 IP 设置里面的

yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses:
        - 192.168.137.100/24
      nameservers:
        addresses: [192.168.137.1] # 这个是 Windows 宿主机在当前虚拟交换机下的 IP
      routes:
        - to: default
          via: 192.168.137.1

里面的

yaml
  ethernets:
    eth0:

保持一致。

Q & A

Q. 如何重置当前节点?比如退出集群?

## reset

```shell
$ sudo kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock