基础知识
CRI、Containerd、OCI、runc
CRI
CRI(Container Runtime Interface)是Kubernetes
定义的接口,定义了如何操作容器和镜像的统一规范。Kubernetes 尽量不关心您使用哪个容器运行时。 它只需要能够向它发送指令——为Pod
创建容器、终止它们等等。 这就是CRI
的用武之地。CRI
是对现在或将来可能存在的任何类型的容器运行时的抽象。 所以 CRI
让 Kubernetes 更容易使用不同的容器运行时。 CRI
API描述了Kubernetes
如何与任何运行时交互,而不是Kubernetes
项目需要单独添加对每个运行时的支持。 只要给定的容器运行时实现了CRI
API,运行时就可以随心所欲地创建和启动容器。
Containerd
containerd
是一个来自Docker
的高级容器运行时,并实现了CRI
规范。它是从Docker
项目中分离出来,之后containerd
被捐赠给云原生计算基金会(CNCF)为容器社区提供创建新容器解决方案的基础。
所以Docker
自己在内部使用containerd
,当你安装Docker
时也会安装containerd
.
containerd
通过其CRI
插件实现了Kubernetes
容器运行时接口(CRI
),它可以管理容器的整个生命周期,包括从镜像的传输、存储到容器的执行、监控再到网络。
OCI
Open Container Initiative 是一个开放的治理结构,其明确目的是围绕容器格式和运行时创建开放的行业标准
Runc
runc 是一个兼容OCI
标准的容器运行时。它实现OCI
规范并运行容器进程。
runc 为容器提供所有低级功能,与现有的低级Linux
功能(如namespaces
和control groups
)交互。它使用这些功能来创建和运行容器进程。
ipvs
todo
环境
主机
软件版本
网段划分
参考另一篇关于网段划分的文章:Kubernetes 集群部署之网段划分
- 宿主机 CIDR
- Kubernetes Service CIDR
- 10.96.0.0/12
- 10.96.0.1 ~ 10.111.255.254
- Kubernetes POD CIDR
- 10.16.0.0/12
- 10.16.0.1 ~ 10.31.255.254
初始化基础环境
除修改hostname
在各自节点执行,其余步骤均需在所有节点执行!!!
修改hostname
此步骤在各自节点执行!!!
1 2 3
| hostnamectl set-hostname master
hostnamectl set-hostname node1
|
yum update
修改hosts文件,使机器可以使用hostname互通
1 2 3 4
| cat >> /etc/hosts <<-EOF 172.16.168.135 master 172.16.168.136 node1 EOF
|
关闭防火墙
1 2 3
| systemctl stop firewalld && systemctl disable firewalld && systemctl status firewalld
|
关闭 selinux
1 2 3 4
| setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
|
关闭 swap
1 2 3 4
| swapoff -a sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
|
配置 iptables 的 ACCEPT 规则
1 2 3
| iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat && iptables -P FORWARD ACCEPT
|
转发 IPv4 并让 iptables 看到桥接流量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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
lsmod | grep br_netfilter lsmod | grep overlay
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
|
安装 ipvs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules
bash /etc/sysconfig/modules/ipvs.modules
lsmod | grep -e ip_vs -e nf_conntrack_ipv4
|
安装 ipset & ipvsadm
1 2 3 4 5 6
| yum install ipset -y
yum install ipvsadm -y
|
同步服务器时间
1 2 3 4 5 6
| yum install chrony -y systemctl enable chronyd systemctl start chronyd chronyc sources
|
安装 containerd
1 2 3 4 5 6 7 8 9
| yum install -y yum-utils
yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
yum install -y containerd.io
|
创建 containerd 配置文件
1 2 3 4 5 6
|
mkdir -p /etc/containerd containerd config default > /etc/containerd/config.toml
sed -i 's#sandbox_image = "registry.k8s.io/pause:3.6"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6"#' /etc/containerd/config.toml
|
对于使用systemd
作为init system
的Linux
发行版,使用systemd
作为容器的cgroup driver
可以确保节点在资源紧张的情况更加稳定,所以推荐将containerd
的cgroup driver
配置为systemd
。[官网文档](https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#cgroup-drivers)
修改前面生成的配置文件/etc/containerd/config.toml
,在plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options
配置块下面将SystemdCgroup
设置为true
,并且kubelet
的cgroupDriver
也要使用systemd
以保持一致。
1 2 3
| sed -i 's#SystemdCgroup = false#SystemdCgroup = true#' /etc/containerd/config.toml
|
启动 containerd
1 2 3 4 5 6 7
| systemctl enable containerd systemctl start containerd systemctl status containerd
ctr version
|
安装三大件
Kubernetes repo
1 2 3 4 5 6 7 8 9 10 11 12
| cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
|
安装 kubeadm、kubelet、kubectl(我安装的指定版本 1.25.3,有版本要求自己设定版本)
1 2 3
| yum install -y kubelet-1.25.3 kubeadm-1.25.3 kubectl-1.25.3
|
设置运行时
1 2 3
| crictl config runtime-endpoint /run/containerd/containerd.sock
|
配置 kubelet 的 cgroup
kubeadm
支持在执行kubeadm init
时,传递一个KubeletConfiguration
结构体。KubeletConfiguration
包含cgroupDriver
字段,可用于控制kubelet
的cgroup
驱动。
在kubeadm
1.22版本后,如果没有在KubeletConfiguration
中设置cgroupDriver
,kubeadm
会将其默认设置为systemd
下面是一个最小化示例,显式的配置了此字段:
1 2 3 4
| --- kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 cgroupDriver: systemd
|
因为我们使用kubeadm
版本较高,所以不用在kubeadm config print init-defaults > kubeadm.yaml
生成的声明文件中配置此项。
将 kubelet 设置成开机启动
此时如果启动kubelet
将会失败,因为kube-apiserver
还没有启动,kubelet
无法建立连接。
1 2 3 4 5
| systemctl daemon-reload
systemctl enable kubelet
|
初始化集群 Master 节点
通过如下命令导出默认的初始化配置
1 2 3
| kubeadm config print init-defaults > kubeadm.yaml
|
修改配置文件
以下仅列出修改的点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| advertiseAddress: 1.2.3.4 name: master
apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta3 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: extraArgs: bind-address: 0.0.0.0
dns: {} etcd: local: dataDir: /var/lib/etcd extraArgs: listen-metrics-urls: http://0.0.0.0:2381 imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers kind: ClusterConfiguration kubernetesVersion: 1.25.3 networking: dnsDomain: cluster.local podSubnet: 10.16.0.0/12 serviceSubnet: 10.96.0.0/12 scheduler: extraArgs: bind-address: 0.0.0.0
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs metricsBindAddress: 0.0.0.0:10249
|
初始化集群
1 2 3
| kubeadm init --config=kubeadm.yaml
|
执行拷贝 kubeconfig 文件
1 2 3
| mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
添加节点(node1
1 2 3
| kubeadm join 172.16.168.135:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:b4b8f89f3bf52cee593e3f385902fff5001b8c87ca2212527725d513dbc15ea2
|
查看集群状态
1 2 3 4 5 6
| [root@master ~] NAME STATUS ROLES AGE VERSION master NotReady control-plane 6m7s v1.25.3 node NotReady <none> 10s v1.25.3
|
安装网络插件
可以看到是NotReady
状态,这是因为还没有安装网络插件,必须部署一个容器网络接口 (CNI)
基于Pod
网络附加组件,以便您的Pod
可以相互通信。在安装网络之前,集群DNS (CoreDNS)
不会启动,这里我们安装calico
,calico文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| wget https://projectcalico.docs.tigera.io/archive/v3.25/manifests/calico.yaml
kubectl apply -f calico.yaml
kubectl get pods -n kube-system
|
至此Kubernetes
安装完成。
部署一个 Deployment 资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
kubectl create deployment nginx --image=nginx:latest -r=3
kubectl get pods
kubectl get deploy
|