树莓派安装 kubernetes v1.27.2
By admin
- 9 minutes read - 1780 wordsUbuntu 22.04.2 LTS ARM64位系统 kubernetes v1.27.2
以前写过一篇安装教程 https://blog.haohtml.com/archives/30924 ,当时安装的版本是 < v1.24.0
版本,由于k8s 从 v1.24.0
版本开始,弃用了 Dockershim
因此没有办法继续使用 Docker Engine
作为运行时,因此如果还想继续使用旧的运行时的话,则需要安装一个 cri-docker
的软件, 本文主要是介绍(版本 >=v1.24.0
)继续使用 Docker Engine
的安装方法,这里以最新版本 v1.27.1
为例。
安装环境初始化
以下内容来自: https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/
执行下述指令:
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
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
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
通过运行以下指令确认 br_netfilter
和 overlay
模块被加载:
lsmod | grep br_netfilter
lsmod | grep overlay
通过运行以下指令确认 net.bridge.bridge-nf-call-iptables
、net.bridge.bridge-nf-call-ip6tables
和 net.ipv4.ip_forward
系统变量在你的 sysctl
配置中被设置为 1:
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
上面添加的两个模块只有在 containerd 运行时才会用到(如果已安装过 docker 的话,则将自动安装此服务)。可以通过命令 systemctl cat containerd.service
查看对模块的引用关系
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
不过这里安装了这两个模块也没有任何影响。
安装 Docker
参考官方文档 https://docs.docker.com/engine/install/ubuntu/ 或aliyun 文档 https://developer.aliyun.com/mirror/docker-ce
修改 cgroupdriver
为 systemd
,同时为了国内访问docker镜像加速,需要设置一下aliyun的 docker 镜像地址
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://gfxrbz51.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
用 docker info
可以验证镜像是否设置成功。
如果使用containerd 运行时的话,则编辑 /etc/containerd/config.toml 文件,注释掉 disabled_plugins = [“cri”] 这一行,执行 systemctl restart containerd 重启服务
安装 cri-docker
安装 cri-docker
以二进制方式安装,也可以使用官方介绍的源码编译方式安装
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.2/cri-dockerd-0.3.2.arm64.tgz
tar -xf cri-dockerd-0.3.2.arm64.tgz
mv cri-dockerd/cri-dockerd /usr/bin/cri-dockerd
curl -L -o /etc/systemd/system/cri-docker.service https://github.com/Mirantis/cri-dockerd/raw/master/packaging/systemd/cri-docker.service
curl -L -o /etc/systemd/system/cri-docker.socket https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
systemctl daemon-reload
systemctl enable --now cri-docker.service
systemctl enable --now cri-docker.socket
启动服务后会生成一个 /var/run/cri-dockerd.sock
文件,这个socket
文件会在下面用到。
安装 kubernetes
$ sudo swapoff -a
建议永久关闭, 在 /etc/fstab
中注释掉 swapfile
这一行。
参考 https://developer.aliyun.com/mirror/kubernetes
安装 k8s 时,将自动安装一个 kubernetes-cni 包,这会在当前宿主机器上的 /opt/cni/bin 目录下看到一些cni插件命令
# ls /opt/cni/bin
bandwidth bridge dhcp dummy firewall host-device host-local ipvlan loopback macvlan portmap ptp sbr static tuning vlan vr
下载k8s所需镜像
# kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers
Found multiple CRI endpoints on the host. Please define which one do you wish to use by setting the 'criSocket' field in the kubeadm configuration file: unix:///var/run/containerd/containerd.sock, unix:///var/run/cri-dockerd.sock
To see the stack trace of this error execute with --v=5 or higher
提示需要指定一个 cri, 我们这里使用cri-docker
# kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --cri-socket unix:///var/run/cri-dockerd.sock
注意后续凡是 kubeadm 命令都要指定这个参数有点麻烦,目前没有找到合适的解决办法。
由于国内网络问题,还需要为 cri-dockerd
指定 infra 容器镜像,编辑文件 /etc/systemd/system/cri-docker.service
,在 ExecStart
指令后面添加 --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9
, 这个镜像上面已下载好了,最终内容如下
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9
然后重启 cri-docker
服务。
systemctl daemon-reload && systemctl restart cri-docker
安装成功后,kubeadm、kubelet 和 kubectl 版本号是一样的,这里它们是写本教程时的最新版本 v1.27.1。
# kubectl version
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short. Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.1", GitCommit:"4c9411232e10168d7b050c49a1b59f6df9d7ea4b", GitTreeState:"clean", BuildDate:"2023-04-14T13:21:19Z", GoVersion:"go1.20.3", Compiler:"gc", Platform:"linux/arm64"}
Kustomize Version: v5.0.1
注意 kubectl 还包含了 Kustomize
命令。
现在我们开始安装 k8s
# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
# kubeadm init --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16 --cri-socket unix:///var/run/cri-dockerd.sock --v=5
这里通过参数 --cri-socket
指定了 CRI cri-dockerd.sock
,这个sock文件路径在上面的 cri-docker.socket
文件配置的。如果不填写则将自动检测,只有当您安装了多个 CRI 或有非标准的 CRI 套接字时才使用此选项。这正是以前 < v1.24.0
版本k8s安装的重要区别地方。
为了以防安装出错,方便排查问题,我们使用了日志等级 --v=5
默认情况下会自动安装与当前kubeadm版本号一致的k8s,另外如果你想安装指定版本号的 k8s 的话,也可以通过参数指定
--kubernetes-version v1.24.0
如果你服务器有多个IP地址的话,默认会读取每一个IP地址,你也可以通过参数指定IP
--apiserver-advertise-address=192.168.0.200
如果你想指定服务IP cidr 的话,则通过参数指定
--service-cidr=10.96.0.0/12
如果不指定此参数,则默认为 10.96.0.0./12
安装成功后,执行提示的命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
这时查看节点和Pods信息
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s NotReady control-plane 10m v1.27.1
# kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7bdc4cb885-lvlc9 0/1 Pending 0 10m
kube-system coredns-7bdc4cb885-nxtd7 0/1 Pending 0 10m
kube-system etcd-k8s 1/1 Running 0 10m
kube-system kube-apiserver-k8s 1/1 Running 0 10m
kube-system kube-controller-manager-k8s 1/1 Running 0 10m
kube-system kube-proxy-qbgtq 1/1 Running 0 10m
kube-system kube-scheduler-k8s 1/1 Running 0 10m
由于没有安装网络插件,所以节点状态为 NotReady
,同时coredns两个 Pods 也不正常。
当调用 kubeadm init
时,kubelet 的配置会被写入磁盘 /var/lib/kubelet/config.yaml
, 并上传到集群 kube-system
命名空间的 kubelet-config
ConfigMap。 kubelet 配置信息也被写入 /etc/kubernetes/kubelet.conf
,其中包含集群内所有 kubelet 的基线配置。 此配置文件指向允许 kubelet 与 API 服务器通信的客户端证书。 这解决了将集群级配置传播到每个 kubelet 的需求。
安装网络插件
这里主要介绍 Flannel 和 Calico 这两个插件,安装任何一个即可。
由于树莓派安装的 Ubuntu22.04.2 系统,而从 ubuntu 21.10版本以后默认移除了对 vxlan 的支持,因此手动安装 xvlan
sudo apt install -y linux-modules-extra-raspi
注意要保证其它加入集群的节点,支持 vxlan
命令。
安装 Flannel 网络插件
下面开始安装Flannel
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
这时发现coredns 状态仍不是 Running
, 查看日志发现无法找到 flannel 生成的网络配置文件 /run/flannel/subnet.env
, 我们手动创建它,内容如下
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false
注意每行末尾没有空格,然后重新部署 flannel 即可。
安装 Calico 网络插件
除了上面提到的 flannel 外,还有 Calico
这个网络插件,我在arm64下安装 flannel
一直遇到容器频繁的重建问题,后来将flannel卸载掉安装了 Calico 解决了问题。
安装教程参考 https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart#install-calico
- 安装 calico operator 和 CRD
# kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/tigera-operator.yaml
- 安装 calico CR
同于 calico 默认的 pod-netowkr-cidr
使用的是 192.168.0.0/16
这个配置,与我们上面指定的 cidr 不一致, 因此没有办法直接用上面的远程安装的方法安装。只能先将文件下载到本地,然后修改 cidr 配置为 10.244.0.0/16
,然后再应用。
# wget https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/custom-resources.yaml | sed 's/192.168/10.244/g' > custome-resources2.yaml
# kubectl create -f custom-resources2.yaml
- 确认所有pod都在运行
# watch kubectl get pods -n calico-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-789dc4c76b-k25kx 1/1 Running 0 6m51s
calico-node-7tf8t 1/1 Running 0 24m
calico-typha-64b645b8b6-4nqmj 1/1 Running 0 24m
csi-node-driver-pm528 2/2 Running 0 24m
等到每个 pod 的状态都为 Running。
如果安装完 Calico 插件后,Master 节点仍是 NotReady 状态,则重启一下 containerd 服务一般就可以解决。
安装完 Calico 后将在 /etc/cni/net.d
目录里创建两个配置文件
# ls /etc/cni/net.d
10-calico.conflist calico-kubeconfig
其中 calico-kubeconfig 内容是与 k8s apiserver 通讯证书配置,而 10-calico-conflist 则是 pod网络配置
# cat /etc/cni/net.d/10-calico.conflist
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico",
"datastore_type": "kubernetes",
"mtu": 0,
"nodename_file_optional": false,
"log_level": "Info",
"log_file_path": "/var/log/calico/cni/cni.log",
"ipam": { "type": "calico-ipam", "assign_ipv4" : "true", "assign_ipv6" : "false"},
"container_settings": {
"allow_ip_forwarding": false
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"k8s_api_root":"https://10.96.0.1:443",
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
},
{"type": "portmap", "snat": true, "capabilities": {"portMappings": true}}
]
}
这里对IP地址管理插件使用的 calico-ipam
这个二进制文件,它同样是在安装 calico 网络插件以后创建的,除此之外另外还生成了 calico
和 install
二进制文件,它位于我们上面提到的 /opt/cni/bin/
目录。可以看一下 plugins 子对象的 type
字段配置的就是 /opt/cni/bin 目录下的二进制文件。
部署 pod 测试
现在我们整个k8s基本安装完毕,我们看一下节点与静态pod服务状态
➜ ubuntu kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s Ready control-plane 4d12h v1.27.1
➜ ubuntu kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-vbzqt 1/1 Running 11 (17m ago) 32m
kube-system coredns-7bdc4cb885-gqcgd 1/1 Running 1 (22m ago) 4d12h
kube-system coredns-7bdc4cb885-n47g8 1/1 Running 1 (22m ago) 4d12h
kube-system etcd-k8s 1/1 Running 1 (22m ago) 4d12h
kube-system kube-apiserver-k8s 1/1 Running 1 (22m ago) 4d12h
kube-system kube-controller-manager-k8s 1/1 Running 1 (22m ago) 4d12h
kube-system kube-proxy-qcmck 1/1 Running 1 (22m ago) 4d12h
kube-system kube-scheduler-k8s 1/1 Running 1 (22m ago) 4d12h
➜ ubuntu kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d12h
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 4d12h
现在节点状态处于 Ready
,所有pod也处于Running
状态,同时还有两个 service
。
现在我们测试利用 deployment 来创建一些pod,由于我这里只有一台机器,为了使用pod也可以被调度到这个节点,还需对此节点进行容忍污点
# kubectl describe node k8s
Taints: node-role.kubernetes.io/control-plane:NoSchedule
...
# kubectl taint nodes k8s node-role.kubernetes.io/control-plane:NoSchedule-
创建一个 nginx-deployment.yml
文件,内容如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.23-alpine
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
#loadBalancerIP: x.y.z.a # 指定公网IP
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer
这里指定了副本 replicas:3
表示创建三个pod,同时声明了一个服务 nginx。
应用配置
kubectl apply -f nginx-deployment.yml
观察pod状态
➜ ubuntu kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 32m
➜ ubuntu kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-984448cf6-bm8xx 1/1 Running 0 32m
nginx-984448cf6-kvhgf 1/1 Running 0 32m
nginx-984448cf6-xtnv5 1/1 Running 0 32m
可以看到 pod 创建成功,但此时服务并分配到任何IP地址,下面我们通过 metallb 来解决这个问题。
crictl
crictl 是一款 Kubelet 容器运行时接口 (CRI) 的 CLI 和验证工具。 crictl 和它的源代码在 cri-tools 代码库。 crictl 不是一个通用的工作流工具,而是一个对调试有用的工具。 介绍文档
首次使用时,需要创建一个默认配置文件 crictl.yaml ,对其进行一些配置
$ cat /etc/crictl.yaml
runtime-endpoint: unix:///var/run/cri-dockerd.sock
image-endpoint: unix:///var/run/cri-dockerd.sock
timeout: 2
debug: true
pull-image-on-create: false
然后我们就可以通过 crictl images
这类的命令查看当前节点的信息,它可以代替一些docker命令,如
ubuntu@k8s:~$ sudo crictl images
DEBU[0000] get image connection
DEBU[0000] ListImagesRequest: &ListImagesRequest{Filter:&ImageFilter{Image:&ImageSpec{Image:,Annotations:map[string]string{},},},}
DEBU[0000] ListImagesResponse: &ListImagesResponse{Images:[]*Image{&Image{Id:sha256:78d0a9e0b092c0dc48cd00423a41785a9ba2980208441c51b9d4adda775dd5a9,RepoTags:[registry.aliyuncs.com/google_containers/kube-apiserver:v1.27.1],RepoDigests:[registry.aliyuncs.com/google_containers/kube-apiserver@sha256:a6daed8429c54f0008910fc4ecc17aefa1dfcd7cc2ff0089570854d4f95213ed],Size_:114714350,Uid:nil,Username:,Spec:nil,Pinned:false,},&Image{Id:sha256:20654f2150dd55dcd4d6c6a7912c34e2d5bf63430f22142e2baabc4612f17d6a,RepoTags:[registry.aliyuncs.com/google_containers/kube-controller-manager:v1.27.1],RepoDigests:[registry.aliyuncs.com/google_containers/kube-controller-manager@sha256:ed43c8f8a78f7bcda715b8427da17a62b22befe236acdc90b24db411e106f481],Size_:107243539,Uid:nil,Username:,Spec:nil,Pinned:false,},&Image{Id:sha256:717e2b2b33bd0fb8a8ce56d1ed46a129e35fd7dc7a41c4079c50e1bf47e61bda,RepoTags:[registry.aliyuncs.com/google_containers/kube-scheduler:v1.27.1],RepoDigests:[registry.aliyuncs.com/google_containers/kube-scheduler@sha256:0b942e32d0d30ca47e2e133e421c7d3bb9cdb01ee972e56d3098e6aced3cdd8a],Size_:56125459,Uid:nil,Username:,Spec:nil,Pinned:false,},&Image{Id:sha256:4ecafc4f7bda115b588241af03ef4a9feb5ec204a2c939ad9bf97b67d728a018,RepoTags:[registry.aliyuncs.com/google_containers/kube-proxy:v1.27.1],RepoDigests:[registry.aliyuncs.com/google_containers/kube-proxy@sha256:958ddb03a4d4d7a567d3563c759a05f3e95aa42ca8af2964aa76867aafc43610],Size_:66499356,Uid:nil,Username:,Spec:nil,Pinned:false,},&Image{Id:sha256:829e9de338bd5fdd3f16f68f83a9fb288fbc8453e881e5d5cfd0f6f2ff72b43e,RepoTags:[registry.aliyuncs.com/google_containers/pause:3.9],RepoDigests:[registry.aliyuncs.com/google_containers/pause@sha256:7031c1b283388d2c2e09b57badb803c05ebed362dc88d84b480cc47f72a21097],Size_:514000,Uid:nil,Username:,Spec:nil,Pinned:false,},},}
IMAGE TAG IMAGE ID SIZE
registry.aliyuncs.com/google_containers/kube-apiserver v1.27.1 78d0a9e0b092c 115MB
registry.aliyuncs.com/google_containers/kube-controller-manager v1.27.1 20654f2150dd5 107MB
registry.aliyuncs.com/google_containers/kube-proxy v1.27.1 4ecafc4f7bda1 66.5MB
registry.aliyuncs.com/google_containers/kube-scheduler v1.27.1 717e2b2b33bd0 56.1MB
registry.aliyuncs.com/google_containers/pause 3.9 829e9de338bd5 514kB
在配置文件里启用了debug,因此最上面才会输出一些信息,一般我们只需要将 debug
设置为 false
。
安装 MetalLB
安装教程参考:
MetalLB 分别使用两个组件来实现了上述两个功能:
- Controller:实现地址分配,以 Deployment 方式运行,用于监听 Service 的变更,分配/回收 IP 地址。
- Speaker:实现地址对外广播,以 DaemonSet 方式运行,对外广播 Service 的 IP 地址。
- 安装MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml
- 配置分配给 Load Balancer Services 的IP池
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.10.0/24
- 192.168.9.1-192.168.9.5
- fc00:f853:0ccd:e799::/124
# autoAssign: false
如果要指定固定的IP的话,则可以使用 192.168.100.10/32
,根据需要修改配置,改成我们计划分配的IP段。
默认情况下,MetalLB将从任何配置的具有可用地址的地址池中分配IP。这可能最终会为不需要的服务使用“昂贵”的地址。
为了防止这种行为,可以通过将autoAssign标志设置为false来禁用池的自动分配。
一旦IP被分配给服务,就必须对其进行公告,主要有两种方式
对于 Layer2 这种配置比较简单,对于大型复杂的网络推荐使用BGP这种配置。
这里为了方便,使用了 Layer2 配置
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
在 L2Advertisement 实例中设置没有 IPAddressPool 选择器被解释为该实例与所有可用的 IPAddressPools 相关联。
因此,如果有专门的IPAddressPools,并且只有其中一些必须通过L2进行广告,则必须声明我们想要广告IP的IPAddress Pools列表(或者,可以使用标签选择器)
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
确认安装是否成功
# kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-7948676b95-xlxc7 1/1 Running 0 3m24s
speaker-nrfsj 1/1 Running 0 3m23s
现在我们再看下对应的服务
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 175m
nginx LoadBalancer 10.105.216.80 192.168.3.220 80:32116/TCP 18s
可以看到此服务分配的IP地址为 `192.168.3.220`,我们用 curl 访问一下
# curl 192.168.3.220
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
可以看到服务是正常的。这里需要说明一下,由是这个ip地址是虚拟IP,只体现在iptables里,因此没有办法通过ping 命令来测试服务是否正常,不过可以通过 telnet 192.168.3.220 80
来测试端口是否正常。
节点加入
如果需要将其它节点加入集群的话,则与上面一样。服务器环境需要先禁用 swap
, 然后安装必须的安装,如 docker
、cri-docker
、kubeadm
和 kubelet
软件,不要忘记了对 cri-docker
的 --pod-infra-container-image
配置。
执行
# sudo kubeadm join 192.168.3.200:6443 --token ulzmn3.98oc7ftd9or3zb42 --discovery-token-ca-cert-hash sha256:1087d7988af2fb1ca066af6d1be8f4ace32f1dd4323cfc756c988093a20d6276 --cri-socket=unix:///var/run/cri-dockerd.sock
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
这里命令也需要指定 cri-docker
参数,过一段时间可以看到新节点已经从 NotReady
变为 Ready
状态,此时我们看一下新节点下载的镜像。
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.aliyuncs.com/google_containers/kube-proxy v1.27.2 29921a084542 10 days ago 66.5MB
calico/typha v3.25.1 1fdaa52c5843 8 weeks ago 59.1MB
calico/cni v3.25.1 d314245e1354 8 weeks ago 192MB
calico/pod2daemon-flexvol v3.25.1 1af18ea84b4d 8 weeks ago 10.5MB
calico/node v3.25.1 273313a9d5b2 8 weeks ago 254MB
quay.io/metallb/speaker v0.13.9 e39bc116ce9a 3 months ago 111MB
registry.aliyuncs.com/google_containers/pause 3.9 829e9de338bd 7 months ago 514kB
这里 registry.aliyuncs.com/google_containers/pause
是在 cri-docker 服务里指定的镜像。
注意有些镜像需要在每个节点都会存在,如 kube-proxy
、calico-node
、csi-node-driver
和 metallb
中的 speaker
。
同时每个节点也会创建一个 vxlan.calico
的网卡
# ifconfig
vxlan.calico: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 10.244.166.128 netmask 255.255.255.255 broadcast 0.0.0.0
inet6 fe80::64f9:37ff:fec3:7e94 prefixlen 64 scopeid 0x20<link>
ether 66:f9:37:c3:7e:94 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 12 overruns 0 carrier 0 collisions 0
一定要确保节点存在此网卡,否则可能跨节点之间的 pod
无法互通的问题,在这一块深有体会。
这里介绍一下 Calico
的 overlay
网络( 文档),对于其实现有两种封装方式,分别为 IPIP
和 VXLAN
。这两种都是通过对数据包进行封装实现,发送端封包而接收端解包。其中 IPIP
也称为 IP IN IP
, 这种封包方式需要 BGP( 文档) ,而 BGP 又分两种拓扑方式,分别为 Full-mesh
(默认拓扑) 和 Route reflectors
。对于节点数 <= 100
的话,一般 Full-mesh
就够用了,而对于节点数 >100
的场景一般推荐使用 Router reflectors
这种拓扑方式。
这两种类型的封装之间有一个小区别是 Calico
的 VXLAN
实现不使用 BGP
,而 Calico
的 IP-in-IP
实现在 Calico
节点之间使用 BGP
。
Calico 的默认 overlay 方式为 VXLAN,因此安装后,在节点会出现一个vxlan.calico 虚拟网卡
常见问题
- 如果遇到 kube-flannel 一直重启的问题,并用命令
journalctl -f -u kubelet.service
查看发现以下错误。May 21 23:57:25 k8s kubelet[753]: I0521 23:57:25.453851 753 scope.go:115] "RemoveContainer" containerID="653cde487a076855b7b37943eeda30bacd1ca02b97d58d8e9b5d3ddece9697d8"May 21 23:57:25 k8s kubelet[753]: E0521 23:57:25.461431 753 pod_workers.go:1281] "Error syncing pod, skipping" err="failed to "StartContainer" for "kube-flannel" with CrashLoopBackOff: "back-off 5m0s restarting failed container=kube-flannel pod=kube-flannel-ds-zm59x_kube-flannel(c6ac2bdf-42a8-4b5e-b09b-6adb6090c1aa)"" pod="kube-flannel/kube-flannel-ds-zm59x" podUID=c6ac2bdf-42a8-4b5e-b09b-6adb6090c1aa
一直未找到是由什么原因引起的,因此我安装了Calico 这个网络插件 - 使用 calico 网络插件,发现不同节点之间的 pod 之间无法通讯。
请确保通讯节点之间是否存在
vxlan-calico
(vxlanMode)这个网卡 或tunl0
(ipipMode)网卡。
参考文章
- https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/
- 将 Docker Engine 节点从 dockershim 迁移到 cri-dockerd
- https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart
- 裸机 Kubernetes 集群负载均衡器: MetalLB 简明教程
- https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/kubelet-integration/
- https://docs.tigera.io/calico/latest/networking/configuring/vxlan-ipip#encapsulation-types
- https://docs.tigera.io/calico/latest/networking/configuring/bgp