使用 Amazon Ec2 + aws-k8s-cni 构建 K8s集群
在AWS上构建Kubernetes(K8S)时,通常使用EKS。
EKS 价格昂贵(每月约 10,000 日元),因此用于验证目的。
在 Amazon Linx2 上构建 K8S。
前提
・您必须拥有 AWS 账户。
注意
由于使用此过程卸载“ec2-net-utils”的影响
重启实例时将不再分配公网IP。
此过程是在公共子网中构建的,用于验证目的,但是
实际上,请将其构建在私有子网中。
准备工作 各资源名称
K8S集群名称:dev-k8s-cluster
K8S 主 EC2:dev-k8s-master
K8S 节点 EC2:dev-k8s-node
创建 EC2 所需的资源
使用 AWS 控制台来完成您的工作。
①创建IAM角色
② 选择可信实体。
实体类型:AWS 服务
使用案例:EC2
③ 选择要使用的角色。
使用的角色:AmazonEC2ContainerRegistryReadOnly
④创建角色。
角色名称:dev-k8s-role
⑤创建安全组
⑥创建安全组。
安全组名称:dev-k8s-security
描述:k8s EC2安全组
专有网络:默认专有网络
*此处无需设置任何带内规则。
创建完成后记下安全组ID。
⑦编辑带内规则。
SSH:我的IP
所有流量: ⑥中记录的安全组ID
创建K8S主EC2
使用 AWS 控制台来完成您的工作。
① 从 EC2 菜单启动实例。
②设置标签。
键:名称,值:dev-k8s-master
Key: kubernetes.io/cluster/dev-k8s-cluster *请替换为您自己的集群名称。 ,价值:拥有
键:k8s-control-plane,值:*可以省略。
③ 为 AMI 设置 Amazon Linux。
④设置实例类型。
实例类型:t3.small
*如果是t3.small,只要启动K8S就会耗尽内存。
如果您需要更多空间,请增加实例类型。
⑤创建密钥对。
密钥对名称:dev-k8s-key
⑥ 设置网络。
选择您在准备过程中创建的现有安全组。
安全组名称:dev-k8s-security
⑦设置存储。
根体积:20G
⑧设置高级详细信息。
在 IAM 实例配置文件中设置准备时创建的角色。
角色名称:dev-k8s-role
⑨启动EC2。
在主EC2上安装K8S
使用teraterm等工具通过SSH登录K8S主EC2并执行工作。
① 确认K8S master EC2的公网IP
从 AWS 控制台的 EC2 列表中检查“dev-k8s-master”的详细信息。
②使用teraterm登录K8S master EC2。
IP:①中确认的公网IP
用户名:ec2-user
密钥文件:上面创建的“dev-k8s-key”
③将EC2更新到最新状态。
sudo yum update –y
|
④卸载ec2-net-utils。
如果安装下面描述的 aws-k8s-cni 插件时包含 ec2-net-utils,
卸载它,因为行为变得不稳定。
1sudo yum remove ec2–net–utils –y
|
⑤ 安装容器运行时。
运行时使用containerd。
sudo amazon–linux–extras enable docker
sudo yum install containerd –y
|
配置containerd自动启动。
sudo systemctl enable —now containerd
|
检查状态。
⑥设置操作系统参数。
cat >>EOF | sudo tee /etc/modules–load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99–containerd.conf
net.bridge.bridge–nf–call–iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge–nf–call–ip6tables = 1
EOF
sudo sysctl —system
|
⑦设置containerd的config.toml。
创建默认设置。
sudo mkdir –p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
|
更改 config.toml 中的参数。
1sudo vi /etc/containerd/config.toml
|
变更详情
[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc]
...
[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc.options]
SystemdCgroup = true # ★ここの値を変更します。
|
反映设置。
1sudo systemctl restart containerd
|
⑧添加tc模块,因为安装kubeadm时会出现警告。
sudo ym install –y tc
|
⑨安装kubeadm、kubelet、kubectl。
添加 K8S 存储库。
sudo vi /etc/yum.repos.d/kubernetes.repo
|
文件内容: /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
|
安装。
*这次我们将安装1.23版本。
1sudo yum install kubelet–1.23.7–0 kubectl–1.23.7–0 kubeadm–1.23.7–0 —disableexcludes=kubernetes –y
|
配置 kubelet 自动启动。
1sudo systemctl enable —now kubelet
|
检查状态。
这里K8S的建设还没有完成,所以处于停止状态。
sudo systemctl status kubelet
|
⑩ 使用kubeadm安装K8S。
创建K8S的配置文件。
vi config.yaml
|
文件内容:config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
criSocket: “/run/containerd/containerd.sock”
—–
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
clusterName: “dev-k8s-cluster” # ★各自クラスタ名に置き換えてください。
controlPlaneEndpoint: ip–172–31–21–87.ap–northeast–1.compute.internal:6443 # ★hostnameコマンド等で取得したホスト名に置き換えてください。
|
使用 kubeadm 命令安装 K8S。
sudo kubeadm init —config config.yaml
|
请注意安装完成后出现的命令。 *上图红框部分
kubeadm join ip–172–31–21–87.ap–northeast–1.compute.internal:6443 —token 6q1g4f.4m1dibndp5h0o5sn \
—discovery–token–ca–cert–hash sha256:cd753371f8fbd3802377ba35809648647a5e6295e09f2de6fb3e00f387fbeddc
|
添加K8S节点时会用到这个,所以一定要记下来。
⑪设置kubectl命令。
配置将 kubectl 命令与 ec2-user 结合使用的设置。
mkdir –p $HOME/.kube
sudo cp –i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id –u):$(id –g) $HOME/.kube/config
|
使用 kubectl 命令检查 pot 的状态。
kubectl get po –A
|
*Coredns 正在等待处理,但这不是问题,因为网络插件尚未安装。
安装K8S网络插件
① 在AWS控制台中为EC2角色添加权限。
角色名称:dev-k8s-role
②在内联策略中输入json。
下面列出了所需的 iam。
amazon-vpc-cni-k8s/iam-policy.md at master · aws/amazon-vpc-cni-k8s
{
“Version”: “2012-10-17″,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [
“ec2:AssignPrivateIpAddresses”,
“ec2:AttachNetworkInterface”,
“ec2:CreateNetworkInterface”,
“ec2:DeleteNetworkInterface”,
“ec2:DescribeInstances”,
“ec2:DescribeTags”,
“ec2:DescribeNetworkInterfaces”,
“ec2:DescribeInstanceTypes”,
“ec2:DetachNetworkInterface”,
“ec2:ModifyNetworkInterfaceAttribute”,
“ec2:UnassignPrivateIpAddresses”,
“ec2:ModifyInstanceAttribute”
],
“Resource”: “*”
},
{
“Effect”: “Allow”,
“Action”: [
“ec2:CreateTags”
],
“Resource”: [
“arn:aws:ec2:*:*:network-interface/*”
]
}
]
}
|
③创建内嵌策略。
内联策略名称:dev-amazon-vpc-cni-k8s
④ 从 git 获取 amazon-vpc-cni-k8s yaml 文件。
安装 git 命令。
sudo yum install git –y
|
这次我们得到的版本是1.11.3
git clone https://github.com/aws/amazon-vpc-cni-k8s.git -b v1.11.3
|
编辑配置文件。
cp amazon–vpc–cni–k8s/config/master/aws–k8s–cni.yaml amazon–vpc–cni–k8s/config/master/aws–k8s–cni.yaml.org
vi amazon–vpc–cni–k8s/config/master/aws–k8s–cni.yaml
|
更改图像源和运行时间。
—–
# Source: aws-vpc-cni/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws–node
namespace: kube–system
labels:
app.kubernetes.io/name: aws–node
app.kubernetes.io/instance: aws–vpc–cni
k8s–app: aws–node
app.kubernetes.io/version: “v1.11.3″
—–
# Source: aws-vpc-cni/templates/customresourcedefinition.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: eniconfigs.crd.k8s.amazonaws.com
labels:
app.kubernetes.io/name: aws–node
app.kubernetes.io/instance: aws–vpc–cni
k8s–app: aws–node
app.kubernetes.io/version: “v1.11.3″
spec:
scope: Cluster
group: crd.k8s.amazonaws.com
preserveUnknownFields: false
versions:
– name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
x–kubernetes–preserve–unknown–fields: true
names:
plural: eniconfigs
singular: eniconfig
kind: ENIConfig
—–
# Source: aws-vpc-cni/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: aws–node
labels:
app.kubernetes.io/name: aws–node
app.kubernetes.io/instance: aws–vpc–cni
k8s–app: aws–node
app.kubernetes.io/version: “v1.11.3″
rules:
– apiGroups:
– crd.k8s.amazonaws.com
resources:
– eniconfigs
verbs: [“list”, “watch”, “get”]
– apiGroups: [“”]
resources:
– namespaces
verbs: [“list”, “watch”, “get”]
– apiGroups: [“”]
resources:
– pods
verbs: [“list”, “watch”, “get”]
– apiGroups: [“”]
resources:
– nodes
verbs: [“list”, “watch”, “get”, “update”]
– apiGroups: [“extensions”]
resources:
– ‘*’
verbs: [“list”, “watch”]
– apiGroups: [“”, “events.k8s.io”]
resources:
– events
verbs: [“create”, “patch”, “list”, “get”]
—–
# Source: aws-vpc-cni/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: aws–node
labels:
app.kubernetes.io/name: aws–node
app.kubernetes.io/instance: aws–vpc–cni
k8s–app: aws–node
app.kubernetes.io/version: “v1.11.3″
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: aws–node
subjects:
– kind: ServiceAccount
name: aws–node
namespace: kube–system
—–
# Source: aws-vpc-cni/templates/daemonset.yaml
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: aws–node
namespace: kube–system
labels:
app.kubernetes.io/name: aws–node
app.kubernetes.io/instance: aws–vpc–cni
k8s–app: aws–node
app.kubernetes.io/version: “v1.11.3″
spec:
updateStrategy:
rollingUpdate:
maxUnavailable: 10%
type: RollingUpdate
selector:
matchLabels:
k8s–app: aws–node
template:
metadata:
labels:
app.kubernetes.io/name: aws–node
app.kubernetes.io/instance: aws–vpc–cni
k8s–app: aws–node
spec:
priorityClassName: “system-node-critical”
serviceAccountName: aws–node
hostNetwork: true
initContainers:
– name: aws–vpc–cni–init
image: “602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon-k8s-cni-init:v1.11.3″ # ★ap-northeast-1に変更
env:
– name: DISABLE_TCP_EARLY_DEMUX
value: “false”
– name: ENABLE_IPv6
value: “false”
securityContext:
privileged: true
volumeMounts:
– mountPath: /host/opt/cni/bin
name: cni–bin–dir
terminationGracePeriodSeconds: 10
tolerations:
– operator: Exists
securityContext:
{}
containers:
– name: aws–node
image: “602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon-k8s-cni:v1.11.3″ # ★ap-northeast-1に変更
ports:
– containerPort: 61678
name: metrics
livenessProbe:
exec:
command:
– /app/grpc–health–probe
– –addr=:50051
– –connect–timeout=5s
– –rpc–timeout=5s
initialDelaySeconds: 60
timeoutSeconds: 10
readinessProbe:
exec:
command:
– /app/grpc–health–probe
– –addr=:50051
– –connect–timeout=5s
– –rpc–timeout=5s
initialDelaySeconds: 1
timeoutSeconds: 10
env:
– name: ADDITIONAL_ENI_TAGS
value: “{}”
– name: AWS_VPC_CNI_NODE_PORT_SUPPORT
value: “true”
– name: AWS_VPC_ENI_MTU
value: “9001”
– name: AWS_VPC_K8S_CNI_CONFIGURE_RPFILTER
value: “false”
– name: AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG
value: “false”
– name: AWS_VPC_K8S_CNI_EXTERNALSNAT
value: “false”
– name: AWS_VPC_K8S_CNI_LOGLEVEL
value: “DEBUG”
– name: AWS_VPC_K8S_CNI_LOG_FILE
value: “/host/var/log/aws-routed-eni/ipamd.log”
– name: AWS_VPC_K8S_CNI_RANDOMIZESNAT
value: “prng”
– name: AWS_VPC_K8S_CNI_VETHPREFIX
value: “eni”
– name: AWS_VPC_K8S_PLUGIN_LOG_FILE
value: “/var/log/aws-routed-eni/plugin.log”
– name: AWS_VPC_K8S_PLUGIN_LOG_LEVEL
value: “DEBUG”
– name: DISABLE_INTROSPECTION
value: “false”
– name: DISABLE_METRICS
value: “false”
– name: DISABLE_NETWORK_RESOURCE_PROVISIONING
value: “false”
– name: ENABLE_IPv4
value: “true”
– name: ENABLE_IPv6
value: “false”
– name: ENABLE_POD_ENI
value: “false”
– name: ENABLE_PREFIX_DELEGATION
value: “false”
– name: WARM_ENI_TARGET
value: “1”
– name: WARM_PREFIX_TARGET
value: “1”
– name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
resources:
requests:
cpu: 25m
securityContext:
capabilities:
add:
– NET_ADMIN
volumeMounts:
– mountPath: /host/opt/cni/bin
name: cni–bin–dir
– mountPath: /host/etc/cni/net.d
name: cni–net–dir
– mountPath: /host/var/log/aws–routed–eni
name: log–dir
– mountPath: /var/run/cri.sock # ★ cri.sockに変更
name: containerd # ★ containerdに変更
– mountPath: /var/run/aws–node
name: run–dir
– mountPath: /run/xtables.lock
name: xtables–lock
volumes:
– name: cni–bin–dir
hostPath:
path: /opt/cni/bin
– name: cni–net–dir
hostPath:
path: /etc/cni/net.d
– name: containerd # ★ containerdに変更
hostPath:
path: /run/containerd/containerd.sock # ★ containerd.sockに変更
– name: log–dir
hostPath:
path: /var/log/aws–routed–eni
type: DirectoryOrCreate
– name: run–dir
hostPath:
path: /var/run/aws–node
type: DirectoryOrCreate
– name: xtables–lock
hostPath:
path: /run/xtables.lock
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
– matchExpressions:
– key: kubernetes.io/os
operator: In
values:
– linux
– key: kubernetes.io/arch
operator: In
values:
– amd64
– arm64
– key: eks.amazonaws.com/compute–type
operator: NotIn
values:
– fargate
|
⑤在K8S上安装。
kubectl apply –f amazon–vpc–cni–k8s/config/master/aws–k8s–cni.yaml
|
使用 kubectl 命令检查 pod 的状态。
kubectl get po –A
|
*当 coredns 变为 Running 时,安装完成。
创建K8S节点EC2。
使用 AWS 控制台来完成您的工作。
① 从 EC2 菜单启动实例。
②设置标签。
键:名称,值:dev-k8s-node
Key: kubernetes.io/cluster/dev-k8s-cluster *请替换为您自己的集群名称。 ,价值:拥有
③ 为 AMI 设置 Amazon Linux。
④设置实例类型和密钥对。
实例类型:t3.small
密钥对名称:dev-k8s-key
⑥ 设置网络。
选择您在准备过程中创建的现有安全组。
安全组名称:dev-k8s-security
⑦设置存储和角色。
根卷:8G *保留默认值。
角色名称:dev-k8s-role
⑧创建EC2。
在节点 EC2 上安装 K8S
使用teraterm等工具登录K8S master EC2并执行工作。
①K8S master EC2全局IP确认
从 AWS 控制台的 EC2 列表中检查“dev-k8s-node”的详细信息。
②使用teraterm登录K8S master EC2。
IP:①中确认的全球IP
用户名:ec2-user
密钥文件:上面创建的“dev-k8s-key”
③EC2を最新の状態にアップデートします。
sudo yum update –y
|
④卸载ec2-net-utils。
如果安装下面描述的 aws-k8s-cni 插件时包含 ec2-net-utils,
卸载它,因为行为变得不稳定。
sudo yum remove ec2–net–utils –y
|
⑤ 安装容器运行时。
运行时使用containerd。
sudo amazon–linux–extras enable docker
sudo yum install containerd –y
|
配置containerd自动启动。
sudo sysemctl enable —now containerd
|
检查状态。
sudo systemctl status containerd
|
⑥设置操作系统参数。
cat <<EOF | sudo tee /etc/modules–load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99–containerd.conf
net.bridge.bridge–nf–call–iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge–nf–call–ip6tables = 1
EOF
sudo sysctl —system
|
⑦设置containerd的config.toml。
创建默认设置。
sudo mkdir –p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
|
更改 config.toml 中的参数。
sudo vi /etc/containerd/config.toml
|
文件内容:config.yaml
[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc]
...
[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc.options]
SystemdCgroup = true # ★ここの値を変更します。
|
反映设置。
sudo systemctl restart containerd
|
⑧添加tc模块,因为安装kubeadm时会出现警告。
sudo yum install –y tc
|
⑨安装kubeadm、kubelet、kubectl。
添加 K8S 存储库。
sudo vi /etc/yum.repos.d/kubernetes.repo
|
文件内容:/etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
|
安装。
*这次我们将安装1.23版本。
sudo yum install kubelet–1.23.7–0 kubectl–1.23.7–0 kubeadm–1.23.7–0 —disableexcludes=kubernetes –y
|
配置 kubelet 自动启动。
sudo systemctl enable —now kubelet
|
检查状态。
这里K8S的建设还没有完成,所以处于停止状态。
sudo systemctl status kubelet
|
⑩ 使用kubeadm链接K8S主EC2。
使用在主 EC2 上安装 K8S 时显示的命令。
使用 sudo 运行它并添加选项“–cri-socket=/run/containerd/containerd.sock”。
sudo kubeadm join ip–172–31–21–87.ap–northeast–1.compute.internal:6443 —token 6q1g4f.4m1dibndp5h0o5sn \
—discovery–token–ca–cert–hash sha256:cd753371f8fbd3802377ba35809648647a5e6295e09f2de6fb3e00f387fbeddc \
—cri–socket=/run/containerd/containerd.sock
|
检查K8S主EC2上的状态。
通过SSH登录K8S主EC2,使用kubectl命令查看节点状态。
kubectl get node
|
如果 STATUS 为“Ready”,则表示正常。
部署示例 nginx。
①创建nginx yaml文件。
文件内容:nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx:1.23.2
ports:
– containerPort: 80
—–
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
– port: 80
|
②部署nginx。
kubectl apply –f nginx.yaml
|
③ 检查nginx的部署情况。
kubectl get po
|
如果 STATUS 为“Runnin”,则表示正常。
④ 检查服务的节点端口。
kubectl get svc
|
检查 PORT 中是否显示“80:30366”。
节点端口将为“30366”。
⑤ 更改安全组,使其可以从外部访问。
登录 AWS 控制台并完成您的工作。
目标安全组:dev-k8s-security
将以下内容添加到您的带内规则中:
类型:自定义 TCP
端口范围:30366 *这是上面确认的节点端口。
来源:我的 IP *这用作我的 IP 以进行验证。 如果您想公开,可以输入“0.0.0.0/0”等。
⑥ 使用浏览器访问nginx。
URL:http://K8S节点EC2公网IP:30366 *这是上面确认的节点端口。
如果显示nginx页面则正常。