将ArchLinux作为节点加入EKS UnmanagedNode
添加一个自管理的节点
添加这个自管理的节点是直接添加进入集群的, 并未使用EKS节点组的概念, 所以这个节点是可以被重启, 或者健康检查失败的, 并不具有任何的扩展或者弹性管理的能力。
创建集群,启动一个新的 EC2, 登录到已经启动的 EKS 优化 OS 内,准备复制一些脚本过来。
添加EC2的标签: kubernetes.io/cluster/clusterName owned
配置EC2的Instance Profile
控制台获取 Kubernetes APIServer的Endpoint URL
获取 apiserver b64 CA :
cat ~/.kube/config
这个文件里面可以找到 ,或者是通过EKS的控制台上面, 找到 Base64 的 CA。编辑 userdata, 或者 ssh 登录到ec2上面创建一个bash脚本用来调用 bootstrap.sh
mkdir ~/eks; touch ~/eks/start.sh --- #!/bin/bash set -ex B64_CLUSTER_CA= API_SERVER_URL= K8S_CLUSTER_DNS_IP=10.100.0.10 /etc/eks/bootstrap.sh ${ClusterName} --b64-cluster-ca ${B64_CLUSTER_CA} --apiserver-endpoint ${API_SERVER_URL}
集群里面没有节点组 , 也不会创建aws-auth configmap 所以节点无法正常的加入集群, 需要手动创建。
apiVersion: v1 data: mapRoles: | - groups: - system:bootstrappers - system:nodes rolearn: [CLUSTER_ROLE] username: system:node:{{EC2PrivateDNSName}} mapUsers: | [] kind: ConfigMap metadata: name: aws-auth namespace: kube-system
需要复制的文件
sudo pacman -S containerd # 安装Containerd
scp /etc/eks/bootstrap.sh root@54.222.253.235:/etc/eks/bootstrap.sh # 复制bootstrap
scp /usr/bin/imds root@54.222.253.235:/usr/bin/imds # shell 脚本, 用来帮忙调用ec2 metadata 获取实例和VPC子网的信息
scp -pr /etc/eks/ root@54.222.253.235:/etc/eks/ # 直接复制了eks的相关脚本和配置模板
scp -pr /var/lib/kubelet/kubeconfig root@54.222.253.235:/var/lib/kubelet/kubeconfig # 复制kubeletconfig配置文件模板
scp -pr /etc/kubernetes/ root@54.222.253.235:/etc/kubernetes/ # 复制 kubernetes 的配置文件
scp -pr /etc/kubernetes/kubelet/ root@54.222.253.235:/etc/kubernetes/kubelet/ # 上面的命令没有递归复制, 所以需要指定
# 设置对应的内核参数, 如果不做kubelet 会报错提示 这些参数不符合要求。
kernel.panic = 10
kernel.panic_on_oops = 1
vm.overcommit_memory = 1
Bootstrap 脚本内容分析
记录一下脚本自动配置的内容, 大概就是 获取变量, aws的服务地址, ec2 元数据地址, 替换模板中的变量生成Kubelet配置文件 和 Containerd 的配置文件(这个替换是一次性的, 也就是说, bootstrap只能变更模板中的变量一次, 第二次执行只会生成刷新一次集群的信息, 以及重启服务)。
- 读取bootstrap后面给出的参数,设置变量, 例如: ClusterName etc.
- 查看Kubelet的版本, 决定Runtime, containerd | dockerd, 判断条件是 kubelet 版本 大于 1.24
++ kubelet --version ++ grep -Eo '[0-9]\.[0-9]+\.[0-9]+' + KUBELET_VERSION=1.24.9 --- + IS_124_OR_GREATER=true + DEFAULT_CONTAINER_RUNTIME=containerd
- 设置ECR以及Pause容器地址
# 获取region以及aws service domain + AWS_DEFAULT_REGION=cn-north-1 + AWS_SERVICES_DOMAIN=amazonaws.com.cn # 调用脚本 /etc/eks/get-ecr-uri.sh cn-north-1 amazonaws.com.cn '' + ECR_URI=918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn + PAUSE_CONTAINER_IMAGE=918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/pause + PAUSE_CONTAINER=918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/pause:3.5 + CA_CERTIFICATE_DIRECTORY=/etc/kubernetes/pki + CA_CERTIFICATE_FILE_PATH=/etc/kubernetes/pki/ca.crt
- 创建证书目录:
+ mkdir -p /etc/kubernetes/pki + sed -i s,MASTER_ENDPOINT,https://CE0253A94B6B14215AE3282580CFA5E3.yl4.cn-north-1.eks.amazonaws.com.cn,g /var/lib/kubelet/kubeconfig + sed -i s,AWS_REGION,cn-north-1,g /var/lib/kubelet/kubeconfig + sed -i s,CLUSTER_NAME,NewClusterForManualJoin,g /var/lib/kubelet/kubeconfig
- 获取 VPC CIDR
# imds shell script help to get metadata. imds: /usr/bin/imds ++ imds latest/meta-data/local-ipv4 ++ imds latest/meta-data/network/interfaces/macs/02:66:06:2e:48:08/vpc-ipv4-cidr-blocks
- 创建kubelet 配置, 计算预留的资源 和 MaxPod 等等参数的数值。
/etc/kubernetes/kubelet/kubelet-config.json + mkdir -p /etc/systemd/system/kubelet.service.d + sudo mkdir -p /etc/containerd + sudo mkdir -p /etc/cni/net.d + sudo mkdir -p /etc/systemd/system/containerd.service.d
- 创建containerd 配置文件
+ printf '[Service]\nSlice=runtime.slice\n' + sudo tee /etc/systemd/system/containerd.service.d/00-runtime-slice.conf + sudo sed -i s,SANDBOX_IMAGE,918309763551.dkr.ecr.cn-north-1.amazonaws.com.cn/eks/pause:3.5,g /etc/eks/containerd/containerd-config.toml
- kubelet配置和启动。
+ sudo cp -v /etc/eks/containerd/kubelet-containerd.service /etc/systemd/system/kubelet.service + sudo chown root:root /etc/systemd/system/kubelet.service + sudo containerd config dump + systemctl enable kubelet + systemctl start kubelet
制作 NodeTemplate AMI
如果使用已经加入过集群的实例直接制作AMI, 节点会无法加入, kubelet报错是APIserver拒绝这个节点的加入。
2023-04-19T15:10:13Z kubelet-eks.daemon[11577]: E0419 15:10:13.325154 11577 event.go:267] Server rejected event '&v1.Event{TypeMeta:v1.TypeMeta{Kind:"", APIVersion:""}, ObjectMeta:v1.ObjectMeta{Name:"ip-10-0-1-249.cn-northwest-1.compute.internal.17575e9c08aefd8d", GenerateName:"", Namespace:"default", SelfLink:"", UID:"", ResourceVersion:"", Generation:0, CreationTimestamp:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), DeletionTimestamp:<nil>, DeletionGracePeriodSeconds:(*int64)(nil), Labels:map[string]string(nil), Annotations:map[string]string(nil), OwnerReferences:[]v1.OwnerReference(nil), Finalizers:[]string(nil), ZZZ_DeprecatedClusterName:"", ManagedFields:[]v1.ManagedFieldsEntry(nil)}, InvolvedObject:v1.ObjectReference{Kind:"Node", Namespace:"", Name:"ip-10-0-1-249.cn-northwest-1.compute.internal", UID:"ip-10-0-1-249.cn-northwest-1.compute.internal", APIVersion:"", ResourceVersion:"", FieldPath:""}, Reason:"NodeHasNoDiskPressure", Message:"Node ip-10-0-1-249.cn-northwest-1.compute.internal status is now: NodeHasNoDiskPressure", Source:v1.EventSource{Component:"kubelet", Host:"ip-10-0-1-249.cn-northwest-1.compute.internal"}, FirstTimestamp:time.Date(2023, time.April, 19, 15, 10, 10, 99764621, time.Local), LastTimestamp:time.Date(2023, time.April, 19, 15, 10, 13, 272025156, time.Local), Count:6, Type:"Normal", EventTime:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), Series:(*v1.EventSeries)(nil), Action:"", Related:(*v1.ObjectReference)(nil), ReportingController:"", ReportingInstance:""}': 'Unauthorized' (will not retry!)
排查所有的地方之后,权限都是正确的, 依旧没发现到底哪里的权限有问题。
发生问题的原因是 已经启动的节点, 有些配置文件已经被更改过了, 写入了固定的信息, 例如apiserver的ca证书, 以及节点的Endpoint地址, 这些文件需要被删除 或者 重新配置,其中最主要的影响 是 /var/lib/kubelet/config 这个配置文件中已经被替换的变量, 还有控制平面错误的CA证书以及信息。
所需处理的文件如下:
root@ip-10-0-1-249:/var/lib/kubelet# ll /var/lib/kubelet/ total 44 drwxr-xr-x 8 root root 4096 Apr 19 15:41 ./ drwxr-xr-x 38 root root 4096 Apr 19 15:40 ../ -rw------- 1 root root 62 Apr 19 15:41 cpu_manager_state drwxr-xr-x 2 root root 4096 Apr 19 15:50 device-plugins/ -rw-r--r-- 1 root root 575 Apr 19 15:41 kubeconfig # 这个目录中唯一存在的一个文件,里面应该是为配置的变量,不能被替换为确定的值。 -rw------- 1 root root 61 Apr 19 15:41 memory_manager_state drwxr-xr-x 2 root root 4096 Apr 19 15:41 pki/ drwxr-x--- 2 root root 4096 Apr 19 15:41 plugins/ drwxr-x--- 2 root root 4096 Apr 19 15:41 plugins_registry/ drwxr-x--- 2 root root 4096 Apr 19 15:41 pod-resources/ drwxr-x--- 8 root root 4096 Apr 19 15:50 pods/ root@ip-10-0-1-249:/etc/kubernetes/pki# ll /etc/kubernetes/pki/ total 12 drwxr-xr-x 2 root root 4096 Apr 19 15:38 ./ drwxr-xr-x 4 root root 4096 Apr 19 15:33 ../ -rw-r--r-- 1 root root 1099 Apr 19 15:41 ca.crt
删除上面目录中的所有文件, 并创建一个新的空文件
touch /var/lib/kubelet/kubeconfig
, 写入内容如下, 保留其中的变量值, 这个部分的变量会在bootstrap的时候替换掉:apiVersion: v1 kind: Config clusters: - cluster: certificate-authority: /etc/kubernetes/pki/ca.crt server: MASTER_ENDPOINT name: kubernetes contexts: - context: cluster: kubernetes user: kubelet name: kubelet current-context: kubelet users: - name: kubelet user: exec: apiVersion: client.authentication.k8s.io/v1beta1 command: /usr/bin/aws-iam-authenticator args: - "token" - "-i" - "CLUSTER_NAME" - --region - "AWS_REGION"
将上面的步骤做完之后关闭实例, 并创建一个新的AMI即可。
当AMI被创建为实例, 并完成运行Bootstrap脚本之后, 所有的节点信息会被重新配置, 这样节点才能正确的加入集群中。