环境:centos 7.9,使用containerd作为容器运行时.
1.环境整理&安装容器运行时
1.28版本无需为cgroup程序选择做额外配置,自动检测使用.
从 v1.22 开始,在使用 kubeadm 创建集群时,如果用户没有在 KubeletConfiguration 下设置 cgroupDriver 字段,kubeadm 默认使用 systemd。
在 Kubernetes v1.28 中,启用 KubeletCgroupDriverFromCRI特性门控结合支持 RuntimeConfig CRI RPC 的容器运行时,kubelet 会自动从运行时检测适当的 Cgroup 驱动程序,并忽略 kubelet 配置中的 cgroupDriver 设置。
使用containerd,那么集成度不像docker.需要使用不同的插件完善功能!
1.1.环境整理
#下列配置基于官方文档
● 每台机器 2 GB 以上的内存,内存不足时应用会受限制。
● 用作控制平面节点的计算机上至少有 2 个 CPU。
● 集群中所有计算机之间具有完全的网络连接。你可以使用公共网络或专用网络。
echo "192.168.174.141 zidingyi
192.168.174.141 master1
192.168.174.142 master2
192.168.174.143 master3
192.168.174.144 node1 " >> /etc/hosts
#在所有节点执行,检查环境
#检查Mac地址是否冲突
ifconfig -a | grep ether
#检查uuid是否冲突
cat /sys/class/dmi/id/product_uuid
#转发IPV4流量并让iptable看到流量,下列配置来自官网
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
#查看是否成功加载模块
lsmod | grep br_netfilter
lsmod | grep overlay
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
#禁用交换分区
swapon && swapoff -a
#查看是否还有
#vim /etc/fstab
#yum -y install netcat > /dev/null || nc 127.0.0.1 6443
1.2.安装containerd
vim /etc/containerd/config.toml
/run/containerd/containerd.sock
#前往github下载二进制包
https://github.com/containerd/containerd/releases
#解压并移动到bin
tar -xf containerd-1.7.9-linux-amd64.tar.gz
cp -r bin/* /usr/local/bin/
#托管给systemd(来自官网),注意修改二进制文件路径.默认位置就是/usr/local/bin/containerd
echo '# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/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
# 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
' > /usr/lib/systemd/system/containerd.service
systemctl daemon-reload
systemctl enable --now containerd
systemctl status containerd
1.3.安装runc
#轻量级的containerd管理工具,但是不好用.不过一般我们也不会去直接操作容器.
#下载
https://github.com/opencontainers/runc/releases
chmod +x runc.amd64
mv runc.amd64 /usr/local/bin/runc
#ctr -v
#必须通过完整镜像和镜像仓库名才能拉取,,
ctr images pull daocloud.io/library/nginx:latest
#查看镜像
ctr images ls
#运行
ctr run -t daocloud.io/library/nginx:latest 名字 bash
1.4.(可选)安装nerdctl
#增强型管理工具,使使用效果与docker命令的语法一致
https://github.com/containerd/nerdctl/releases
tar -xf nerdctl-1.7.0-linux-amd64.tar.gz
mv nerdctl /usr/local/bin/
nerdctl version
#你也可以 alias docker=nerdctl
1.5.安装 cni
#Container network interface容器网络接口,为容器分配ip地址网卡等
https://github.com/containernetworking/plugins/releases
#必须指定为这个目录!#创建目录,必须放到此目录
mkdir -p /opt/cni/bin/
tar -xf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin/
#测试,在网页打开ip:8888
nerdctl run -d -p 8888:80 --name=web --restart=always daocloud.io/library/nginx:latest
1.6. 配置containerd加速
#生成containerd默认配置文件
mkdir /etc/containerd
containerd config default > /etc/containerd/config.toml
#修改runc使用systemd cgroup
#sed -ri 's/ systemd_cgroup = false/ systemd_cgroup = true/' /etc/containerd/config.toml
vim /etc/containerd/config.toml
搜索plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
将SystemdCgroup = true改成true
#修改sandbox_image为国内地址
sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9"
#配置镜像加速
搜索plugins."io.containerd.grpc.v1.cri".registry.mirrors]
在后面添加
[plugins."io.containerd.grpc.v1.cri".registry.mirrors] #此为上述原句,注意缩进!
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["http://mirrors.ustc.edu.cn"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."*"]
endpoint = ["http://hub-mirror.c.163.com"]
#重启
systemctl restart containerd
netstat -nlput | grep containerd
2.安装kubelet/kubeadm/kubectl
kubadm不会自动安装kubadm和kublet,它们的版本最好相同.一次性安装它们
控制平面版本可以高于kublet一个版本.但最好不要这样.
cat >/etc/yum.repos.d/kubernetes.repo<<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
#exclude=kubelet kubeadm kubectl
EOF
setenforce 0
yum install -y kubelet-1.28.1 kubeadm-1.28.1 kubectl-1.28.1 --nogpgcheck
systemctl enable --now kubelet
#kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环。你用systemctl status查询它是一直在启动中,没逝的.
3.创建高可用集群
3.1 初始主节点(控制平面)
3.1.1 初始化
#查看集群所需的镜像
kubeadm config images list
#使用国内镜像,而不是官方镜像~因此需要
kubeadm config images list | awk -F'/' '{print $2}'
#可以指定版本
--kubernetes-version=1.28.0
#使用脚本拉取镜像,这一步可以忽略,直接初始化也会自动拉取.
tee k8s_images.sh<<'EF'
#!/bin/bash
images=$(kubeadm config images list | awk -F'/' '{print $2}')
for i in ${images}
do
nerdctl pull registry.aliyuncs.com/google_containers/$i
done
EF
chmod +x k8s_images.sh && ./k8s_images.sh
#初始化
echo "192.168.174.141 zidingyi" >> /etc/hosts
swapoff -a
kubeadm init \
--kubernetes-version=1.28.1 \
--control-plane-endpoint=zidingyi \
--apiserver-advertise-address=192.168.174.141 \
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.100.0.0/16
#参数解释
init 初始化
--kubernetes-version指定版本
--apiserver-advertise-address指定master地址,不能出现冲突
--control-plane-endpoint指定高可用集群的访问端点,必须做域名解析!!
--image-repository指定镜像仓库
--service-cidr指定service资源对象的ip范围,不能出现冲突
--pod-network-cidr指定pod资源对象的ip范围,不能出现冲突,后面会使用calico插件进行网络通信
--ignore-preflight-errors=Swap关于swap的错误忽略
--cri-socket指定cri接口的Socket文件
##安装完成的信息最好复制出来
##慎用!重置节点!
#sudo kubeadm reset --force
#sudo rm -rf /var/lib/etcd
#sudo rm -rf /var/lib/kubelet /etc/kubernetes /var/lib/cni
#sudo reboot
3.1.2 成功安装信息
#下面的这些信息请务必复制出来
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/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join zidingyi:6443 --token dnuela.raar4890unjtk7cd \
--discovery-token-ca-cert-hash sha256:fb9fff5**** \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join zidingyi:6443 --token dnuela.raar4890unjtk7cd \
--discovery-token-ca-cert-hash sha256:fb9fff5****
#根据安装完成信息进行操作
#1.授权管理员配置文件,这里面储存了集群所需的认证和授权信息
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#2.将master节点加入集群
kubeadm join zidingyi:6443 --token dnuela.raar4890unjtk7cd \
--discovery-token-ca-cert-hash sha256:fb9fff5**** \
--control-plane
#3.非node节点使用此命令加入集群
kubeadm join cluster-endpoint:6443 --token slvdor.rw30ppgeqqiu7osz \
--discovery-token-ca-cert-hash sha256:fb9fff5****
3.1.3 按要求执行操作
在所有的控制平面"主节点"加入集群后都要进行操作
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get nodes
3.2 Calico 网络插件
#用来集群通信的,只需要在一个主节点安装
#确认版本对应的calico插件版本
#注意,下列的latest表示版本!请根据官网给的版本自行更改搜索
https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements
#查到3.26版本是当前最新的版本,且支持1.28的k8s
wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml
#修改其中的配置,主要是网段改成我们指定的pod的10.100.0.0/16网段
vim calico.yaml
将注释打开,且必须注意格式!!!!
name: CALICO_IPV4POOL_CIDR
value: "10.100.0.0/1"
#查看状态-A全部 -w同步,看到全部running继续~
kubectl get pod -A -w
#看一眼集群状态
kubectl get nodes
3.3 主节点加入集群控制平面
#1.要互相做域名解析
echo '
192.168.174.141 zidingyi
192.168.174.141 master1
192.168.174.142 master2
192.168.174.143 master3 ' >> /etc/hosts
#2.手动添加证书!
ssh master2 'mkdir -p /etc/kubernetes/pki/etcd'
scp -rp /etc/kubernetes/pki/ca.* master2:/etc/kubernetes/pki
scp -rp /etc/kubernetes/pki/sa.* master2:/etc/kubernetes/pki
scp -rp /etc/kubernetes/pki/front-proxy-ca.* master2:/etc/kubernetes/pki
scp -rp /etc/kubernetes/pki/etcd/ca.* master2:/etc/kubernetes/pki/etcd
scp -rp /etc/kubernetes/admin.conf master2:/etc/kubernetes
#加入节点
kubeadm join zidingyi:6443 --token uni7tg.6c19bu9zi0u1nluj --discovery-token-ca-cert-hash sha256:fb9fff****** --control-plane
#储存授权信息,每个主节点都必须做,否则会出问题!
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get nodes
3.4 工作节点加入集群
echo '
192.168.174.141 zidingyi
192.168.174.141 master1
192.168.174.142 master2
192.168.174.143 master3
192.168.174.144 node1 ' >> /etc/hosts
kubeadm join zidingyi:6443 --token uni7tg.6c19bu9zi0u1nluj --discovery-token-ca-cert-hash sha256:fb9fff******
4.Dashboard
4.1 部署
#建议去官方文档看看版本https://kubernetes.io/zh-cn/docs/tasks/access-application-cluster/web-ui-dashboard/
#注意:必须确保你有至少一个node(工作)节点可以用来运行dashboard,master节点默认是不会被分配pod的.
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
kubectl apply -f recommended.yaml
#修改配置文件,使用节点ip端口访问
#先看一眼服务,发现只有pod的ip和端口..这样外界是无法访问的!
kubectl get svc -A |grep kubernetes-dashboard
#编辑service,来自命名空间kubernetes-dashboard,的服务kubernetes-dashboard
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
查询修改 type: ClusterIP 为 type: NodePort
#查看端口映射
kubectl get svc -A |grep kubernetes-dashboard
kubernetes-dashboard kubernetes-dashboard NodePort 10.96.108.112 <none> 443:31536/TCP 6m21s
#现在可以访问节点IP192.168.174.141+端口31536访问,注意是https!因为是443端口!
https://192.168.174.141:31536
4.1.1 查询
#查看deployment是否正常维持指定命名空间的pod副本数量
kubectl get deployments --namespace=kubernetes-dashboard
#查看关于这个服务的详细描述
kubectl describe service kubernetes-dashboard --namespace=kubernetes-dashboard
#查看端口映射
kubectl get service kubernetes-dashboard --namespace=kubernetes-dashboard
#查看集群的全部地址
kubectl get nodes -o wide
4.2 创建访问帐号ServiceAccount
并不算真正意义上的"帐号",而是一个凭证,在这里用来请求原来不能请求的"资源".Dashboard实际运行在Node节点上.但是Node节点一般是没有权限在管理其它节点的.
echo 'apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard' > dash.yml
kubectl apply -f dash.yml
4.2.1 详解
apiVersion: v1 # 指定 API 版本,这里 v1 是 ServiceAccount 的 API 版本
kind: ServiceAccount # 指定资源类型,这里创建的是一个 ServiceAccount,service资源对象,会被允许通过这个配置通过调用API
metadata: # 资源的元数据,可以认为是配置"传参"的开始标志
name: admin-user # 设定名称
namespace: kubernetes-dashboard # 设定所在的命名空间
---#表示另一个配置的开始,分隔
apiVersion: rbac.authorization.k8s.io/v1 # 指定 RBAC(基于角色的访问控制) 授权的 API 版本,简单来说是设定指定的"角色"能做什么.这将在后续的配置中定义.
kind: ClusterRoleBinding # 指定资源类型,这里创建的是一个集群角色关联,用来关联上述创建的账号和对象(即kubernetes-dashboard).
metadata: # 资源的元数据,可以认为是配置"传参"的开始标志
name: admin-user # 上述创建的帐号的名称
roleRef: # 角色引用,指定了绑定的角色信息
apiGroup: rbac.authorization.k8s.io # 指定角色所属的 API 组
kind: ClusterRole # 指定角色的种类
name: cluster-admin # 角色中预定义的名称,拥有集群资源的完全控制权限.
#这个配置将创建的ServiceAccount: admin-user绑定了ClusterRole角色中拥有完全控制权限的cluster-admin.从而使kubernetes-dashboard作为使用者能完全控制集群!
subjects: # 对象列表,指出哪些用户/用户组/服务账户将被赋予角色
- kind: ServiceAccount # 指定对象类型为 ServiceAccount
name: admin-user # 指定为上面创建的 ServiceAccount账号.
namespace: kubernetes-dashboard # 指定 ServiceAccount 所在的命名空间进行使用
4.3 创建访问的token
echo 'apiVersion: v1
kind: Secret
metadata:
name: admin-user
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: "admin-user"
type: kubernetes.io/service-account-token ' > sec.yml
kubectl apply -f sec.yml
#获取
kubectl get secret admin-user -n kubernetes-dashboard -o jsonpath={".data.token"} | base64 -d
4.3.1 详解
apiVersion: v1 # 指定api版本
kind: Secret # 表明这是一个Secret资源类型
metadata: #元数据,可以理解成将改动以元数据的方式存储/下面的配置传参到这个kind~
name: admin-user # Secret资源的名称,是之前定义的一个高权限的角色名称
namespace: kubernetes-dashboard # Secret所处的命名空间
annotations: #表示注释,以键值对方式注释~
kubernetes.io/service-account.name: "admin-user" # 注释说明这个Secret与哪个服务账户关联
type: kubernetes.io/service-account-token # Secret的类型,表示它是用来存储服务账户token的
控制器 获取 对象是这个 名称是这个 指定命名空间 输出指定格式是json,对象是{}
kubectl get secret admin-user -n kubernetes-dashboard -o jsonpath={".data.token"} | base64 -d
#最后用管道符传递解码base64格式为原始值; -d表示解码base64编码数据的参数,比如
#echo 'c29tZS1lbmNvZGVkLXN0cmluZw==' | base64 -d
5.问题排查
calico报错 not ready
#查看pod状态,发现有一个节点没有正常运行,杀了这个pod自动重启也无效
kube-system calico-node-ss72d 0/1 Running 0 3m38s
#问gpt
看起来这个问题是由于Calico节点上的BIRD进程未能与其他节点上的BGP对等体建立连接
应该是网桥的问题,问问度娘怎么做
https://developer.aliyun.com/article/1100883
简单来说就是配置文件中使用自动获取BGP导致的
kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=interface=eth0
#daemonset.apps/calico-node env updated表示成功
#设定calico的环境变量IP_AUTODETECTION_METHOD=interface=eth0,指定使用eth0网卡的值