作者简介
王瀚兴,SUSE 软件工程师,首要担任 Rancher 产品线相关的研制造业。
欧拉开源社区的 RFO SIG 正在尽力将 openEuler 与 Rancher 整合,以推进社区的云原生版图开展。而 openEuler 如安在云环境开箱即用是一个非常重要的根底,接受上篇文章,本篇将首要介绍 openEuler AWS AMI 镜像制造的详细过程。
经过创立 AWS AMI 镜像可将 openEuler 与 AWS 云服务相结合,支撑云环境中规范的 ssh key注入、分区扩容、用户数据履行等功能,并运用 cloud-init 机制完结主动发动 Rancher RKE2 集群。往后,openEuler Cloud Images 的作业也将成为 RFO SIG 的一部分,逐步扩展支撑更多的云渠道。
调整硬盘分区巨细
openEuler 官方供给的 qcow2 格局的镜像为一个总磁盘巨细为 40G 的虚拟机镜像,在 qemu 中发动虚拟机,检查分区情况。
能够看到磁盘含有两个分区,其间 2G 为 boot 分区,38G 为 root 分区。
运用 Net Based Disk (NBD) 将 qcow2 镜像的分区加载到 Linux 体系中,之后运用 resize2fs 紧缩 ext4 文件体系的体积,并运用分区调整东西 fdisk 调整分区的巨细。
# 加载 NBD 内核模块
$ sudo modprobe nbd max_part=3
# 加载 qcow2 镜像中的分区至体系
sudo qemu-nbd -c "/dev/nbd0" "openEuler-22.03-LTS-x86_64.qcow2"
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nbd0 43:0 0 40G 0 disk
|-nbd0p1 43:1 0 2G 0 part
|-nbd0p2 43:2 0 38G 0 part
# 调整 ext4 文件体系巨细至6G
$ sudo resize2fs /dev/nbd0p2 6G
# 运用fdisk调整分区巨细至6G
$ sudo fdisk /dev/nbd0
Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): d
Partition number (1,2, default 2): 2
Partition 2 has been deleted.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (2-4, default 2): 2
First sector (4194304-83886079, default 4194304):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (4194304-83886079, default 83886079): +6G
Created a new partition 2 of type 'Linux' and of size 6 GiB.
Partition 2 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: N
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
# 从体系中卸载 qcow2 镜像的分区
$ sudo qemu-nbd -d /dev/nbd0
之后运用 qemu-img 将 qcow2 镜像缩小至8G,并转化为 RAW 格局。
$ qemu-img resize openEuler-22.03-LTS-x86_64.qcow2 --shrink 8G
$ qemu-img convert openEuler-22.03-LTS-x86_64.qcow2 openEuler-22.03-LTS-x86_64.raw
Snapshot 和 Base AMI 的创立
首先运用 awscli 供给的东西,将 RAW 镜像上传至 AWS S3 bucket 中。
$ aws s3 cp openEuler-22.03-LTS-x86_64.raw s3://${BUCKET_NAME}/
创立 vmimport policy 和 role policy。
$ cat << EOF > trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "vmie.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals":{
"sts:Externalid": "vmimport"
}
}
}
]
}
EOF
$ aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json
$ cat << EOF > role-policy.json
{
"Version":"2012-10-17",
"Statement":[
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::${BUCKET_NAME}",
"arn:aws:s3:::${BUCKET_NAME}/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject",
"s3:GetBucketAcl"
],
"Resource": [
"arn:aws:s3:::${BUCKET_NAME}",
"arn:aws:s3:::${BUCKET_NAME}/*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:ModifySnapshotAttribute",
"ec2:CopySnapshot",
"ec2:RegisterImage",
"ec2:Describe*"
],
"Resource": "*"
}
]
}
EOF
$ aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json
创立 import-snapshot 使命,将存储在 S3 bucket 的 RAW 镜像创立为 Snapshot。
$ aws ec2 import-snapshot \
--description "openEuler RAW image import task" \
--disk-container \
"Format=RAW,UserBucket={S3Bucket=${BUCKET_NAME},S3Key=openEuler-22.03-LTS-x86_64.raw}"
等候几分钟后,经过 import task ID 获取导入成功后的 Snapshot ID。
$ aws ec2 describe-import-snapshot-tasks \
--import-task-ids ${IMPORT_TAST_ID}
运用此 Snapshot 创立不含 cloud init 机制的 Base AMI 镜像。
$ aws ec2 register-image \
--name "DEV-openEuler-22.03-LTS-x86_64-BASE" \
--description "DEV openEuler image, do not use for production!" \
--root-device-name /dev/xvda \
--architecture x86_64 \
--ena-support \
--virtualization-type hvm \
--block-device-mappings \
DeviceName=/dev/xvda,Ebs={SnapshotId=${SNAPSHOT_ID}}
至此,咱们获得了 Base AMI ID。
运用 Packer 创立包含 Cloud init 机制的 AMI 镜像
首先创立 Packer 的配置文件,留意修正配置文件中的 <BASE_AMI_ID> 为刚刚获取的 Base AMI ID。
{
"variables": {
"version": "{{env `OPENEULER_VERSION`}}",
"build": "{{env `AWS_IMAGE_BUILD_NUMBER`}}",
"arch": "{{env `OPENEULER_ARCH`}}"
},
"builders": [
{
"type": "amazon-ebs",
"name": "amazon-ebs-hvm-x86_64",
"region": "ap-northeast-1",
"ami_regions": [
"ap-northeast-1"
],
"source_ami": "<BASE_AMI_ID>",
"instance_type": "t3a.micro",
"ssh_username": "root",
"ssh_password": "openEuler12#$",
"ami_name": "openEuler-{{user `version`}}-x86_64-hvm-{{user `build`}}",
"ena_support": "true"
}
],
"provisioners": [
{
"type": "shell",
"environment_vars": [
"VERSION={{user `version`}}",
"ARCH={{user `arch`}}"
],
"script": "./install-cloudinit.sh"
}
]
}
新建脚本文件 install-cloudinit.sh,用来履行装置 cloud init 和其他配置的指令。
#!/bin/bash
set -e
yum -y update
yum -y install cloud-init cloud-utils-growpart gdisk
yum -y install vim tar make zip gzip wget git tmux \
conntrack-tools socat iptables-services htop
# disable Apparmor
echo "GRUB_CMDLINE_LINUX_DEFAULT=\"apparmor=0\"" >> /etc/default/grub
# Update grub config
if [[ "$(uname -m)" == "x86_64" ]]; then
grub2-mkconfig -o /boot/grub2/grub.cfg
elif [[ "$(uname -m)" == "arm64" ]]; then
grub2-mkconfig -o /boot/efi/EFI/openEuler/grub.cfg
fi
最后运用以下指令运用 packer 构建 AMI 镜像。
$ packer build <PACKER_CONFIG.json>
构建 ARM 架构的 AMI 镜像
理论上构建 ARM 架构的 AMI 镜像的全体流程与 x86_64 架构的流程几乎共同,但是在实际操作过程中遇到了运用 Base AMI 镜像发动服务器后找不到网卡设备而无法 ssh 连接到服务器的情况。
在运用串口连接到服务器上进行调试后发现,ARM 架构的 openEuler 体系的内核中没有预装 AWS ENA 网卡驱动,所以无法访问网络连接。
后续 openEuler 会为 ARM 架构的内核增添 ENA 驱动支撑,在此之前可运用编译 ENA 驱动内核模块并导入的方式,作为一个暂时的解决办法,感兴趣的朋友能够参考一下。
此办法只能作为一个暂时的解决方法,不主张用作出产环境中。
首先在本地运转一个用来编译内核模块的 openEuler aarch64 虚拟机,装置 gcc,make,git,vim 内核头文件等编译需要的东西,克隆 ENA 驱动的源码到本地并编译。
$ yum -y install make git gcc vim kernel-devel-$(uname -r)
$ git clone git clone https://github.com/amzn/amzn-drivers.git
$ cd amzn-drivers/kernel/linux/ena/
$ make -j2
编写这篇文章时,在编译的过程中会遇到这个报错:
/root/amzn-drivers/kernel/linux/ena/ena_ethtool.c:1218:19: error: initialization of ‘int (*)(struct net_device *, struct ethtool_coalesce *, struct kernel_ethtool_coalesce *, struct netlink_ext_ack *)’ from incompatible pointer type ‘int (*)(struct net_device *, struct ethtool_coalesce *)’ [-Werror=incompatible-pointer-types]
1218 | .get_coalesce = ena_get_coalesce,
| ^~~~~~~~~~~~~~~~
compilation terminated due to -Wfatal-errors.
一个比较直接的解决办法是修改 ena_ethtool.c,在 1218-1221 行,为这几个函数指针添加 (void*) 强制的指针类型转化。
编译后会生成 ena.ko 内核模块文件,可用 modinfo ena.ko 检查该模块的信息。
$ modinfo ena.ko
filename: /root/amzn-drivers/kernel/linux/ena/ena.ko
version: 2.8.0g
license: GPL
description: Elastic Network Adapter (ENA)
author: Amazon.com, Inc. or its affiliates
......
在调整硬盘分区时,挂载分区,复制此内核模块文件到挂载的分区的目录中并修改 modprobe 配置文件,在每次开机发动时都加载这个内核模块。
# 假定将分区挂载到了 /mnt 目录下面
$ sudo mount /dev/nbd0p2 /mnt
# 这里将内核模块复制到了 /root 目录下面
$ sudo cp ./ena.ko /mnt/root/
$ sudo bash -c ' echo "install ena insmod /root/ena.ko" >> /mnt/etc/modprobe.d/ena.conf '
$ sudo bash -c ' echo "ena" >> mnt/etc/modules-load.d/ena.conf '
$ sudo sync && sudo umount /mnt
重启体系后,能够运用 lsmod 检查已加载的内核模块,或运用 dmesg 检查内核日志,能够看到 ENA 驱动被加载的记载。
$ sudo lsmod
Module Size Used by
ena 147456 0
......
$ dmesg | grep ena:
[ 94.814488] ena: loading out-of-tree module taints kernel.
[ 94.814896] ena: module verification failed: signature and/or required key missing - tainting kernel
现在 openEuler 社区已修复了 ARM 架构的内核不包含 ENA 网卡驱动的问题,会在后续的内核更新中获取到包含 ENA 驱动的内核。更多信息可在此PR中获取到:gitee.com/openeuler/k…
已构建的 AMI 镜像运用
在 AWS EC2 实例的控制台页面,运用构建的 AMI 镜像创立一个 EC2 虚拟机,设定网络安全组、SSH 密钥、磁盘巨细、用户数据等配置。
在本篇文章中,设定的 EBS 磁盘巨细为 30G,在用户数据中填写了装置 RKE2 的脚本:
#!/bin/bash
echo "-------- Start custom user data ----------"
yum update
curl -sfL https://get.rke2.io > install.sh
chmod +x ./install.sh
sudo INSTALL_RKE2_METHOD=tar ./install.sh
sudo systemctl enable rke2-server
sudo systemctl start rke2-server
echo "-------- User data finished successfully -----------"
实例发动后,cloud init 机制会主动创立用户名为 openeuler 的账号并设定仅运用 ssh key 登录,同时 root 账号的 ssh 登录也会被禁止。磁盘的 root 分区会主动扩容到咱们设定的 EBS 磁盘巨细,用户数据中填写的脚本也将被主动履行。
检查 cloud init 输出的日志,其间包含用户数据的履行结果:
$ tail -f /var/log/cloud-init-output.log
Is this ok [y/N]: Operation aborted.
[INFO] finding release for channel stable
[INFO] using v1.24.4+rke2r1 as release
[INFO] downloading checksums at https://github.com/rancher/rke2/releases/download/v1.24.4+rke2r1/sha256sum-amd64.txt
[INFO] downloading tarball at https://github.com/rancher/rke2/releases/download/v1.24.4+rke2r1/rke2.linux-amd64.tar.gz
[INFO] verifying tarball
[INFO] unpacking tarball file to /usr/local
Created symlink /etc/systemd/system/multi-user.target.wants/rke2-server.service → /usr/local/lib/systemd/system/rke2-server.service.
-------- User data finished successfully -----------
Cloud-init v. 21.4 finished at Wed, 21 Sep 2022 06:56:30 +0000. Datasource DataSourceEc2Local. Up 130.47 seconds
验证分区主动扩容至总容量为设定的 EBS 的巨细:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 30G 0 disk
├─nvme0n1p1 259:1 0 2G 0 part /boot
└─nvme0n1p2 259:2 0 28G 0 part /
验证 RKE2 装置成功,所有 pods 均正常发动:
$ sudo /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml get nodes
NAME STATUS ROLES AGE VERSION
ip-172-31-21-213.ap-northeast-1.compute.internal Ready control-plane,etcd,master 7m58s v1.24.4+rke2r1
$ sudo /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system cloud-controller-manager-ip-172-31-21-213.ap-northeast-1.compute.internal 1/1 Running 0 14m
kube-system etcd-ip-172-31-21-213.ap-northeast-1.compute.internal 1/1 Running 0 14m
kube-system helm-install-rke2-canal-l5rnl 0/1 Completed 0 14m
kube-system helm-install-rke2-coredns-jckq7 0/1 Completed 0 14m
kube-system helm-install-rke2-ingress-nginx-dxcsc 0/1 Completed 0 14m
kube-system helm-install-rke2-metrics-server-kgjdf 0/1 Completed 0 14m
kube-system kube-apiserver-ip-172-31-21-213.ap-northeast-1.compute.internal 1/1 Running 0 14m
kube-system kube-controller-manager-ip-172-31-21-213.ap-northeast-1.compute.internal 1/1 Running 0 14m
kube-system kube-proxy-ip-172-31-21-213.ap-northeast-1.compute.internal 1/1 Running 0 14m
kube-system kube-scheduler-ip-172-31-21-213.ap-northeast-1.compute.internal 1/1 Running 0 14m
kube-system rke2-canal-ng2sw 2/2 Running 0 13m
kube-system rke2-coredns-rke2-coredns-76cb76d66-nklrw 1/1 Running 0 13m
kube-system rke2-coredns-rke2-coredns-autoscaler-58867f8fc5-mpgd7 1/1 Running 0 13m
kube-system rke2-ingress-nginx-controller-fhpbd 1/1 Running 0 12m
kube-system rke2-metrics-server-6979d95f95-2lrp8 1/1 Running 0 13m
About SUSE Rancher
Rancher是一个开源的企业级Kubernetes办理渠道,完结了Kubernetes集群在混合云+本地数据中心的集中部署与办理。Rancher一贯因操作体验的直观、极简备受用户喜爱,被Forrester评为“2020年多云容器开发渠道领导厂商”以及“2018年全球容器办理渠道领导厂商”,被Gartner评为“2017年全球最酷的云根底设施供货商”。
现在Rancher在全球具有超过三亿的中心镜像下载量,并具有包含我国联通、我国安全、我国人寿、上汽集团、三星、施耐德电气、西门子、育碧游戏、LINE、WWK保险集团、澳电讯公司、德国铁路、厦门航空、新东方等全球著名企业在内的共40000家企业客户。
2020年12月,SUSE完结收购RancherLabs,Rancher成为了SUSE “立异无处不在(Innovate Everywhere)”企业愿景的要害组成部分。SUSE和Rancher共同为客户供给了无与伦比的自在和所向披靡的立异才能,经过混合云IT根底架构、云原生转型和IT运维解决方案,简化、现代化并加速企业数字化转型,推进立异无处不在。
当前,SUSE及Rancher在我国大陆及港澳台地区的业务,均由数硕软件(北京)有限公司承载。SUSE在国内具有优秀的研制团队、技能支撑团队和销售团队,将结合Rancher领先的云原生技能,为我国的企业客户供给愈加及时和可信赖的技能支撑及服务保障。