先决条件

官方提供的EKS集群架构如图,本文参考官方架构,使用EC2构建自建集群。
在这里插入图片描述

创建VPC

创建两个VPC,一个host作为控制平面,一个pod作为数据平面,如图所示(这里是我构建的一个测试demo),地区(region)、可用区(availability zone)、VPC和子网(subnet)都可以按自己需求分分配。

在这里插入图片描述

创建网络

根据如上图所示的架构创建网络

创建公网网络

在这里插入图片描述

  1. 创建互联网网关并关联到VPC
  2. 创建弹性网络(分配公网ip地址),此步骤也可以选择自动分配公网ip,可以避免手动创建

创建与配置EC2实例

使用EKS托管服务推荐使用EKS节点的镜像,而自建则取决于系统要求,这里选用Amazon Linux

  1. 创建EC2实例

1)每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)。
2)控制平面机器需要 CPU 2 核心或更多。

在这里插入图片描述
2. 绑定弹性ip到私有ip(让虚拟机能访问互联网)
在这里插入图片描述

使用ssh客户端连接EC2

通过密钥等方式使用弹性ip(公网ip)连接到云虚拟机,如图所示即连接成功
在这里插入图片描述

在EC2虚拟机上安装K8s

  1. 更新源
sudo yum -y update
  1. K8s必须启用bridge-nf-call-iptables内核参数

加载网络驱动

sudo modprobe br_netfilter

添加参数

cat <<EOF | sudo tee -a /etc/sysctl.conf > /dev/null
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward=1
EOF

### 生效
sudo sysctl -p

安装容器运行时

K8s官方文档指出支持三种容器运行时:containerd、CRI-O、Docker Engine(使用 cri-dockerd),本文以containerd为例。
值得注意的是GIthub - containerd 指出,通过源获得containerd的方式只有通过Docker,此方法安装过于臃肿,因此本文采用下载二进制的方法安装。

The containerd.io packages in DEB and RPM formats are distributed by Docker (not by the containerd project). See the Docker documentation for how to set up apt-get or dnf to install containerd.io packages:

  1. 安装containerd

下载并安装containerd二进制文件

wget https://github.com/containerd/containerd/releases/download/v2.1.4/containerd-2.1.4-linux-amd64.tar.gz
sudo tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gz

### 可选,使用systemd启动containerd
sudo mkdir -p /usr/local/lib/systemd/system/
wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo mv containerd.service /usr/local/lib/systemd/system/

启动containerd服务

sudo systemctl daemon-reload
sudo systemctl enable --now containerd

### 构建默认配置,不执行此步骤在ubuntu环境会报错,需要进入root用户执行
sudo -i
mkdir -p /etc/containerd && containerd config default > /etc/containerd/config.toml
exit
  1. 安装runc

下载并安装runc二进制文件

wget https://github.com/opencontainers/runc/releases/download/v1.4.0-rc.2/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
  1. 安装cni

下载并安装cni二进制文件

wget https://github.com/containernetworking/plugins/releases/download/v1.8.0/cni-plugins-linux-amd64-v1.8.0.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.8.0.tgz

关闭SELinux

### 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
sudo setenforce 0

或(官方教程提供,以下指令适用于 Kubernetes 1.33)

sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

安装K8s

  1. 添加yum源
# 此操作会覆盖 /etc/yum.repos.d/kubernetes.repo 中现存的所有配置
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
  1. 安装kubelet、kubeadm、kubectl
    如果一次只安装一个,crictl和kubectl在安装kubeadm时作为依赖被自动安装,同理,k8s-cni在安装kubelet时作为依赖被自动安装)
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
  1. 初始化K8s集群
sudo kubeadm init --pod-network-cidr=192.168.0.0/24

安装网络插件

安装网络插件之后,pod和node节点才能联网,dns服务才能正常启动。

安装K8s插件
# 例如 Flannel:
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/refs/heads/master/Documentation/kube-flannel.yml
# 或 Calico(常用):
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml
# 或 Cilium:
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/main/install/kubernetes/quick-install.yaml
安装amazon-vpc-cni-k8s插件(可选)

如果直接在自建EC2集群上安装该插件,会发现无法拉取,报错如下 :

Failed to pull image “602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init:v1.16.4”: failed to pull and unpack image “602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init:v1.16.4”: failed to resolve reference “amazon-k8s-cni-init:v1.16.4”: pull access denied, repository does not exist or may require authorization: authorization failed: no basic auth credential

先决条件
  1. 为以下两个文件添加--cloud-provider=external
sudo vim /etc/kubernetes/manifests/kube-controller-manager.yaml
sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml
  1. 下载ecr-credential-provider,负责提供私有镜像认证
curl -o ecr-credential-provider https://storage.googleapis.com/k8s-artifacts-prod/binaries/cloud-provider-aws/v1.29.0/linux/amd64/ecr-credential-provider-linux-amd64
sudo mv ecr-credential-provider /usr/bin/ecr-credential-provider
sudo chmod +x /usr/bin/ecr-credential-provider

mkdir -p $HOME/.aws
cat <<EOF | sudo tee $HOME/.aws/credential-config.yaml > /dev/null
apiVersion: kubelet.config.k8s.io/v1
kind: CredentialProviderConfig
providers:
  - name: ecr-credential-provider
    matchImages:
      - "*.dkr.ecr.*.amazonaws.com"
    defaultCacheDuration: "12h"
    apiVersion: credentialprovider.kubelet.k8s.io/v1
    env:
EOF
  1. 修改kubelet启动参数
sudo vim /etc/sysconfig/kubelet

### 添加以下参数
KUBELET_EXTRA_ARGS="--node-ip=<X.X.X.X> --node-labels=node.kubernetes.io/node= --cloud-provider=external --image-credential-provider-config=$HOME/.aws/credential-config.yaml --image-credential-provider-bin-dir=/usr/bin"

### 重启服务
sudo systemctl daemon-reload && sudo systemctl restart kubelet.service
安装aws-k8s-cni插件
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/refs/heads/master/config/master/aws-k8s-cni.yaml

Q&A

  1. 报错hostname不能访问

[preflight] Running pre-flight checks
[WARNING FileExisting-tc]: tc not found in system path
[WARNING Hostname]: hostname “XXX” could not be reached
[WARNING Hostname]: hostname “XXX”: lookup XXX on X.X.X.X:X: no such host

  • 获取主机 IP
NODE_IP=$(hostname -I | awk '{print $1}')
  • 更新 /etc/hosts
sudo sed -i "/$(hostname)/d" /etc/hosts
echo "$NODE_IP $(hostname)" | sudo tee -a /etc/hosts
  1. pod/集群无限重启 (CrashLoopBackOff)
Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------

  Normal   BackOff    4m2s (x43 over 14m)  kubelet            Back-off pulling image "XXX"
  Warning  Failed     4m2s (x43 over 14m)  kubelet            Error: ImagePullBackOff

【注意不要用此方法安装!!!】 Amazon提供了两个二进制版本,containerd-2.0.6-1.amzn2023.0.1.x86_64runc-1.2.6-1.amzn2023.0.1.x86_64(runc在安装containerd时作为依赖被安装)

dnf install -y containerd
当集群崩溃无法查看集群状态时的其他办法

查看系统pod状态

### 如果此方法无法连接到集群
kubectl describe pod [pod-name] --namespace=kube-system

### 通过cri查看状态 
sudo crictl ps -a | egrep 'apiserver|controller|scheduler|etcd' || true

### 打印现在集群
kubeadm token create --print-join-command

参考文献
[1].安装 kubeadm官方指南.https://v1-33.docs.kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
[2].使用 Amazon VPC CNI 插件搭建自定义网络环境的 Kubernetes 集群.https://aws.amazon.com/cn/blogs/china/use-amazon-vpc-cni-build-default-net-kubernetes-groups/
[3]Using amazon-vpc-cni-k8s outside eks.https://github.com/aws/amazon-vpc-cni-k8s/issues/2839

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐