本地VMWare环境搭建1.28版本K8S

环境规划

k8s环境规划

podSubnet(pod网段) 10.244.0.0/16

serviceSubnet(service网段): 10.96.0.0/12

实验环境规划

操作系统:centos7.9

配置: 1Gib内存/8vCPU/20G硬盘

网络:NAT模式

K8S集群角色 IP 主机名 安装的组件
控制节点 192.168.40.180 master-1 apiserver、controller-manager、scheduler、kubelet、etcd、kube-proxy、容器运行时、calico
工作节点 192.168.40.181 node-1 Kube-proxy、calico、coredns、容器运行时、kubelet
工作节点 192.168.40.182 node-2 Kube-proxy、calico、coredns、容器运行时、kubelet

虚拟机准备

配置VMware虚拟机

  • 安装VMware
  • 下载CentOS7镜像
  • 配置VMWare虚拟机,使用NAT模式。
  • 安装CentOS系统

配置CentOS虚拟机网络

  • 新搭建出来的虚拟机默认没有IP,需要先修改配置文件加一个IP

  • vmware-编辑-虚拟机网络编辑器,先把网段和子网掩码设置好:

image-20231228195437108

  • 修改网卡配置文件
vi /etc/sysconfig/network-scripts/ifcfg-ens33

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static #static表示静态ip地址
IPADDR=192.168.40.180 #ip地址,需要跟自己电脑所在网段一致
NETMASK=255.255.255.0
GATEWAY=192.168.40.2
DNS1=192.168.40.2
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33 #网卡名字,跟DEVICE名字保持一致即可
DEVICE=ens33 #网卡设备名,ip addr可看到自己的这个网卡设备名
ONBOOT=yes #开机自启动网络,必须是yes

关闭Selinux

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
reboot

SSH连接

  • VSCod直接配置ssh host文件用内网IP登录。

免密登录

  • 客户端ssh-keygen生成公钥

  • 把公钥复制到服务器端

mkdir -p ~/.ssh/
touch ~/.ssh/authorized_keys
vi ~/.ssh/authorized_keys
#将公钥值复制进去
  • 编辑ssh配置文件
sudo vim /etc/ssh/sshd_config
#PubkeyAuthentication yes注释去掉,才可以使用公钥验证
  • 重启ssh服务
systemctl restart sshd.service 
  • VsCode的ssh配置文件中加入公钥位置
Host 192.168.40.180
  HostName 192.168.40.180
  User root
  IdentityFile /C:/Users/hangx/.ssh/id_rsa

克隆两台工作节点

  • 虚拟机关机-右键克隆出两台新机器

  • 修改两台机器网卡配置文件,配置静态IP

vi /etc/sysconfig/network-scripts/ifcfg-ens33
#IP修改成192.168.40.181,192.168.40.182

配置k8s环境准备

替换阿里云repo源

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum makecache

替换阿里云的epel源

yum install -y wget
wget -O /etc/yum.repos.d/epel-7.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache

升级系统到centos7.9

yum update -y

配置主机名

hostnamectl set-hostname master-1 && bash 
hostnamectl set-hostname node-1 && bash 
hostnamectl set-hostname node-2 && bash 

配置hosts文件

vim /etc/hosts

192.168.40.180   master-1  
192.168.40.181   node-1  
192.168.40.182   node-2

tee -a /etc/hosts <<'EOF'
172.16.183.75 master1
172.16.183.76 node1
EOF

配置主机间无密码登录

ssh-keygen
ssh-copy-id master-1
ssh-copy-id node-1
ssh-copy-id node-2

关闭交换分区

swapoff -a
vim /etc/fstab
#/dev/mapper/centos-swap swap      swap    defaults        0 0

配置阿里云repo源

  • 配置基础repo源
#备份基础repo源
mkdir /root/repo.bak
cd /etc/yum.repos.d/
mv * /root/repo.bak/
#课件里面的阿里云的repo源
#把CentOS-Base.repo和epel.repo文件上传到master1主机的/etc/yum.repos.d/目录下
chmod o+w /etc/yum.repos.d
  • 配置阿里云docker的repo源
yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
#会把阿里云的docker源的配置给拉下来。
  • 配置安装k8s组件的阿里云repo源
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=0
EOF

安装基础软件包

yum install -y device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel  python-devel epel-release openssh-server socat  ipvsadm conntrack telnet ipvsadm openssh-clients

yum install如果出现报错:GPG key retrieval failed: [Errno 14] curl#37 - "Couldn't open file /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7"

意思是,yum源开启了GPG校验,需要在/etc/pki/rpm-gpg目录下存在对应安装文件的公钥文件,才能完成校验。

可以关闭掉校验:

sed -i 's/pgcheck=1/pgcheck=0/g' /etc/yum.repos.d/epel.repo

配置时间同步

#安装ntpdate命令
yum install ntpdate -y
#跟网络时间做同步
ntpdate cn.pool.ntp.org
#把时间同步做成计划任务
crontab -e
* */1 * * * /usr/sbin/ntpdate   cn.pool.ntp.org
#重启crond服务
service crond restart

禁用firewalld

systemctl stop firewalld && systemctl disable firewalld

修改内核参数-开路由转发

modprobe br_netfilter 
echo "modprobe br_netfilter" >> /etc/profile

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

sysctl -p /etc/sysctl.d/k8s.conf 

安装K8S组件

安装配置containerd

yum install containerd.io-1.6.6 -y #1.27也是用这个版本
#生成 containerd 的配置文件:
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

#修改配置文件,1.26和1.27配置一样
#SystemdCgroup = true表示containerd驱动用systemd,在 Kubernetes 中,容器运行时需要与宿主机的 cgroup 和 namespace 进行交互,以管理容器的资源。
#对于 cgroup 的驱动程序,Docker 和 Containerd 默认都使用的是 cgroupfs。#systemd-cgroup 则是 Systemd 对 cgroup 的一个实现。
#相比 cgroupfs,systemd-cgroup 在资源隔离方面提供了更好的性能和更多的特性。例如,systemd-cgroup 可以使用更多的内存压缩算法,以便更有效地使用内存。此外,systemd-cgroup 还提供了更好的 cgroup 监控和控制机制,可以更精确地调整容器的资源使用量。总之,使用 systemd-cgroup 作为容器运行时的 cgroup 驱动程序,可以提高 Kubernetes 集群中容器的资源管理效率,从而提升整个集群的性能。

#将sandbox_image设置为阿里云镜像仓库中的pause:3.7,在 Kubernetes 中,每个 Pod 中都有一个 pause 容器,这个容器不会运行任何应用,只是简单地 sleep。它的作用是为了保证 Pod 中所有的容器共享同一个网络命名空间和 IPC 命名空间。pause 容器会在 Pod 的初始化过程中首先启动,然后为 Pod 中的其他容器创建对应的网络和 IPC 命名空间,并且在其他容器启动之前保持运行状态,以保证其他容器可以加入到共享的命名空间中。
#简单来说,pause 容器就是一个占位符,它为 Pod 中的其他容器提供了一个共享的环境,使它们可以共享同一个网络和 IPC 命名空间。这也是 Kubernetes 实现容器间通信和网络隔离的重要机制之一。
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
vim /etc/containerd/config.toml
sandbox_image = "k8s.gcr.io/pause:3.6" ==> sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7"

#配置 containerd 开机启动,并启动 containerd
systemctl enable containerd --now

#修改/etc/crictl.yaml文件,指定k8s的运行时和拉取镜像都使用containerd
#这个文件是 crictl 工具的配置文件,用于指定与 containerd 交互的相关设置:
#指定unix:///run/containerd/containerd.sock 是为了告诉 crictl 使用 Unix 域套接字的方式来连接 containerd 的 API。containerd 提供了一个 socket 文件 /run/containerd/containerd.sock,crictl 通过连接该 socket 文件,可以与 containerd 进行通信,管理容器和镜像等操作。
#runtime-endpoint:指定 containerd 的运行时接口地址:crictl 可以与 containerd 通信来管理容器生命周期和资源隔离。
#image-endpoint:指定 containerd 的镜像接口地址:以便 crictl 可以与 containerd 通信来管理镜像的拉取和推送。
#timeout:指定 crictl 等待 containerd 响应的最大时间,避免出现无响应的情况。
#debug:开启或关闭 crictl 的调试模式,方便排查问题。

cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
systemctl restart containerd

#配置containerd镜像加速器,k8s所有节点均按照以下配置:
mkdir /etc/containerd/certs.d/docker.io/ -p
tee -a /etc/containerd/certs.d/docker.io/hosts.toml <<'EOF'
[host."https://docker.m.daocloud.io"]
  capabilities = ["pull"]
EOF

vim /etc/containerd/config.toml
config_path = "" ==> config_path = "/etc/containerd/certs.d"
#保存退出
systemctl restart containerd

ctr和crictl区别

  • 背景:在部署k8s的过程中,经常要对镜像进行操作(拉取、删除、查看等)

  • 问题:使用过程中会发现ctr和crictl有很多相同功能,也有些不同,那区别到底在哪里?

  • 说明:

  • ctr是containerd自带的CLI命令行工具,crictl是k8s中CRI(容器运行时接口)的客户端,k8s使用该客户端和containerd进行交互;

cat /etc/crictl.yaml 
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
pull-image-on-create: false
disable-pull-on-run: false

2.ctr和crictl命令具体区别如下,也可以--help查看。

  • crictl缺少对具体镜像的管理能力,可能是k8s层面镜像管理可以由用户自行控制,能配置pod里面容器的统一镜像仓库,镜像的管理可以有habor等插件进行处理。

image-20231023220844831

(注:docker save -o打包的镜像,用ctr -n=k8s.io images import可以解压出来)

安装配置docker

#docker也要安装,docker跟containerd不冲突,安装docker是为了能基于dockerfile构建镜像
yum install docker-ce -y
systemctl enable docker --now
#配置docker镜像加速器,k8s所有节点均按照以下配置
tee /etc/docker/daemon.json <<'EOF'
{
 "registry-mirrors":["https://docker.m.daocloud.io"]
} 
EOF
#重启docker:
systemctl daemon-reload && systemctl restart docker && systemctl status docker

k8s舍弃dockershim

background: Dockershim FAQ

  • Kubernetes 的早期版本仅适用于特定的容器运行时:Docker Engine。后来,Kubernetes 增加了对使用其他容器运行时的支持。创建 CRI 标准是为了和许多不同的容器运行时之间交互操作。
  • Docker Engine 没有实现(CRI)接口,因此 Kubernetes 项目创建了特殊代码来帮助过渡,并使 dockershim 代码成为 Kubernetes 的一部分。dockershim 代码一直是一个临时解决方案(因此得名:shim)。事实上,维护 dockershim 已经成为 Kubernetes 维护者的沉重负担。
  • 此外,在较新的 CRI 运行时中实现了与 dockershim 不兼容的功能,例如 cgroups v2 和用户命名空间。 从 Kubernetes 中移除 dockershim 允许在这些领域进行进一步的开发。
  • 舍弃dockershim,但是docker技术还是有用的,因为要用dockerfile和docker build做镜像。这个功能是其他容器运行时没有的。

舍弃dockershim带来的优势:

  • 调用链上看 - 用containerd更高效
  • 用dockerd作为容器运行时:kubelet --> dockershim --> dockerd --> containerd
  • 用containerd作为容器运行时:kubelet --> CRI pulgin (containerd进程内) --> containerd

  • 资源利用率上看 - 用containerd更精简

  • Docker不是一个纯粹的容器运行时,具有大量其他功能

containerd和docker作为容器运行时的区别

  • 拉取镜像时:
#containerd需要写明完整镜像路径
ctr -n=k8s.io images pull docker.io/library/centos:latest
#docker拉镜像可以简写
docker pull centos

安装k8s软件包

yum install -y kubelet-1.28.1 kubeadm-1.28.1 kubectl-1.28.1
systemctl enable kubelet

初始化集群

  • 设置容器运行时
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
#这个在先前/etc/crictl.yaml中已经配置过了
  • 使用kubeadm初始化k8s集群
#在控制节点上
cd /root/
kubeadm config print init-defaults > kubeadm.yaml
#根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,需要注意的是由于我们使用的containerd作为运行时,所以在初始化节点的时候需要指定cgroupDriver为systemd
  • kubeadm.yaml配置文件如下:
tee kubeadm.yaml << 'EOF'
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.40.180 #控制节点的ip
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock ##指定containerd容器运行时
  imagePullPolicy: IfNotPresent
  name: master-1 #控制节点主机名
  taints: 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 #这是kubeadm安装控制节点组件时用的镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.28.1 #这里的版本要和kubeadm\kubectl\kubelet的版本一致
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16 #指定pod网段
  serviceSubnet: 10.96.0.0/12
scheduler: {}

---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF
  • 初始化集群
kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification
#配置kubectl的配置文件config,相当于对kubectl进行授权,这样kubectl命令可以使用这个证书对k8s集群进行管理
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

#1. 设置kubectl的alias为k:
whereis kubectl # kubectl: /usr/bin/kubectl
echo "alias k=/usr/bin/kubectl">>/etc/profile
source /etc/profile

#2. 设置alias的自动补全:
source <(kubectl completion bash | sed 's/kubectl/k/g')

#3. 解决每次启动k都会失效,要重新刷新环境变量(source /etc/profile)的问题:在~/.bashrc文件中添加以下代码:source /etc/profile
echo "source /etc/profile" >> ~/.bashrc

#4. 给alias k也配置补全
tee -a ~/.bashrc <<'EOF'
alias k='kubectl'
complete -o default -F __start_kubectl k
source <(kubectl completion bash)
EOF

##使命令生效
source ~/.bashrc

#安装了zsh的环境,把上面放到~/.zshrc中
echo "source /etc/profile" >> ~/.zshrc 

~/.bashrc 是一个在 Linux 系统中的 shell 脚本,当用户打开新的 bash shell 时,它会被自动执行。这个文件通常用于定义环境变量,别名,函数等,以便在打开新的 bash shell 时自动设置这些值。

例如,如果你想要为所有的 bash shell 设置一个环境变量 JAVA_HOME,你可以在 ~/.bashrc 文件中添加以下行:

export JAVA_HOME=/path/to/java

注意,~/.bashrc 文件是针对单个用户的。如果你想要为系统中的所有用户设置环境变量或别名,你应该编辑 /etc/bash.bashrc/etc/profile 文件。

  • 扩容工作节点
kubeadm token create --print-join-command
#在node-01上加参数 --ignore-preflight-errors=SystemVerification
#工作节点打标签
kubectl label nodes node2 node-role.kubernetes.io/work=worker

mkdir -p $HOME/.kube
#master-01的kubectl的config文件拷到node1上
scp $HOME/.kube/config node-1:/root/.kube/

安装calico

#上传了Caclio.yaml
kubectl apply -f calico.yaml
#在线下载地址为:https://docs.projectcalico.org/manifests/calico.yaml

#修改calico配置
#- name: CLUSTER_TYPE
#  value: "k8s,bgp"
# 上面这一段的下面添加:(指定calico从ens33跨节点通信,不指定的话,会走lo的IP,没办法跨节点通信,也就没办法给pod划分IP)
- name: IP_AUTODETECTION_METHOD
  value: "interface=ens33"

#验证calico功能
kubectl run busybox --image docker.io/library/busybox:1.28  --image-pull-policy=IfNotPresent --restart=Never --rm -it busybox -- sh
#ping外网
ping www.baidu.com
#nslookup svc
nslookup kubernetes.default.svc.cluster.local