【Kubernetes】在AWS的EC2上从零构建kubeadm
先决条件
官方提供的EKS集群架构如图,本文参考官方架构,使用EC2构建自建集群。
创建VPC
创建两个VPC,一个host作为控制平面,一个pod作为数据平面,如图所示(这里是我构建的一个测试demo),地区(region)、可用区(availability zone)、VPC和子网(subnet)都可以按自己需求分分配。

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

- 创建互联网网关并关联到VPC
- 创建弹性网络(分配公网ip地址),此步骤也可以选择自动分配公网ip,可以避免手动创建
创建与配置EC2实例
使用EKS托管服务推荐使用EKS节点的镜像,而自建则取决于系统要求,这里选用Amazon Linux
- 创建EC2实例
1)每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)。
2)控制平面机器需要 CPU 2 核心或更多。

2. 绑定弹性ip到私有ip(让虚拟机能访问互联网)
使用ssh客户端连接EC2
通过密钥等方式使用弹性ip(公网ip)连接到云虚拟机,如图所示即连接成功
在EC2虚拟机上安装K8s
- 更新源
sudo yum -y update
- 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:
- 安装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
- 安装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
- 安装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
- 添加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
- 安装kubelet、kubeadm、kubectl
如果一次只安装一个,crictl和kubectl在安装kubeadm时作为依赖被自动安装,同理,k8s-cni在安装kubelet时作为依赖被自动安装)
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
- 初始化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
先决条件
- 为以下两个文件添加
--cloud-provider=external
sudo vim /etc/kubernetes/manifests/kube-controller-manager.yaml
sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml
- 下载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
- 修改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
- 报错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
- 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_64,runc-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
更多推荐

所有评论(0)