1. 简介
本文介绍了如何解决在中国区通过CDK内置方法安装EKS Helm Chart失败的问题。经过总结,安装失败主要是由于AWS中国区网络问题无法访问到相应的Repository,具体分为以下两种情况:
- Helm Chart Repository无法访问
- Helm Chart 所依赖的特定Image无法访问
本文会对这两种情况具体给出几种解决方案,需要注意的是本文所采用的CDK版本为2.27.0,在不同版本下具体操作步骤会有些许区别
1. 1 关于 Helm Chart
Helm 是一款当下流行的基于Kubernetes的应用包管理工具。开发者按照Helm Chart的格式,将应用所需的资源文件包装起来,通过模版化的方式将一些可变字段暴露给用户,最后将封装好的应用包,也就是Helm Chart,集中存放在统一的仓库中供用户浏览下载。用户只需要一行简单的命令就可以完成应用的安装、卸载与升级。对于安装之后状态,也可以通过 helm list 或者是原生的 kubectl 进行查询。
1. 2 CDK安装Helm Chart原理
AWS CDK提供了内置方法给EKS Cluster安装Helm Chart,aws_cdk.aws_eks.Cluster.add_helm_chart。实现方法是通过部署一个预定义好的Lambda函数,通过 helm upgrade 命令以及用户输入的参数,安装指定Helm Chart。但是如果Helm Chart的配置中包含特定域名的Repository则会安装失败,例如gcr.io。
2. Helm Chart Repository 无法访问解决方案
这里以通过CDK安装“aws-efs-csi-driver”Helm Chart为例,以下代码在Global Region测试通过
awsefscsi_chart = eks_cluster.add_helm_chart(
"aws-efs-csi-driver",
chart="aws-efs-csi-driver",
version="2.2.5",
release="awsefscsidriver",
repository="https://kubernetes-sigs.github.io/aws-efs-csi-driver/",
namespace="xxx",
values={
},
)
在中国区运行 cdk deploy 出现以下报错信息,可以确认为无法访问Helm Chart的应用包
下午6:21:22 | CREATE_FAILED | Custom::AWSCDK-EKS-HelmChart | clusterchartawsefscsidriverFB9E01B8
Received response status [FAILED] from custom resource. Message returned: Error: b'Release "awsefscsidriver" does not exist. Installing it now.\nE
rror: failed to download "https://github.com/kubernetes-sigs/aws-efs-csi-driver/releases/download/helm-chart-aws-efs-csi-driver-2.2.5/aws-efs-csi-driver-2.2.5.tgz" at version "2.2.5" (hint: running helm repo update may help)\n'
2. 1 下载Helm Chart到本地,通过CDK内置方式上传
可以通过浏览器访问指定Repository,或者通过 helm pull 命令,下载相应Helm Chart到本地,将.tgz文件解压缩或者打包成.zip文件。需要注意通过VPN访问外网,或者通过Global Region的Cloud9来进行操作,这里不做赘述。
在CDK中import Helm Chart目录为Asset,然后在 add_helm_chart 中添加 chart_asset 参数,并且注释掉chart,version,repository参数,即可正常安装本地Helm Chart,同样以“aws-efs-csi-driver”为例
import aws_cdk.aws_s3_assets as s3_assets
chart_asset = s3_assets.Asset(
self,
"aws-efs-csi-driver",
path='./aws-efs-csi-driver/'
)
efscsi_chart = eks_cluster.add_helm_chart(
"aws-efs-csi-driver",
#chart="aws-efs-csi-driver",
#version="2.2.5",
release="awsefscsidriver",
#repository="https://kubernetes-sigs.github.io/aws-efs-csi-driver/",
chart_asset=chart_asset,
namespace="xxx",
values={
},
)
2. 2 手动Pull & Push Helm Chart到中国区ECR
首先本地安装Helm 3.5.4,需注意CDK 2.27.0自带的Helm版本为3.5.4,因此本地不能用超过3.7版本的 helm push 否则安装会失败。通过以下命令安装指定版本的Helm
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/getchmod +x get_helm.sh
./get_helm.sh -v v3.5.4
按照2. 1中的方法下载Helm Chart到本地,再通过以下命令push到ECR
aws ecr create-repository --repository-name <chart_name>
aws ecr get-login-password \
--region cn-north-1 | helm registry login \
--username AWS \
--password-stdin <account_id>.dkr.ecr.cn-north-1.amazonaws.com.cn
helm chart save <chart_name>.tgz <account_id>.dkr.ecr.cn-north-1.amazonaws.com.cn/<chart_name>:<version>
helm chart push <account_id>.dkr.ecr.cn-north-1.amazonaws.com.cn/<chart_name>:<version>
查看push结果,注意”imageManifestMediaType”和”artifactMediaType”两个字段。
aws ecr describe-images —repository-name <chart_name>
{
"imageDetails": [
{
"registryId": "",
"repositoryName": <chart_name>,
"imageDigest": "",
"imageTags": [
<version>
],
"imageSizeInBytes": ,
"imagePushedAt": "",
"imageManifestMediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactMediaType": "application/vnd.cncf.helm.config.v1+json"
}
]
}
若Helm版本高于3.7,则可以通过官方文档所写步骤push Helm Chart到ECR
https://docs.aws.amazon.com/zh_cn/AmazonECR/latest/userguide/push-oci-artifact.html
成功push到ECR之后,CDK中add_helm_chart方法,将repository参数替换为ECR Image URI。
awsefscsi_chart = eks_cluster.add_helm_chart(
"aws-efs-csi-driver",
chart="aws-efs-csi-driver",
version="2.2.5",
release="awsefscsidriver",
repository="<account_id>.dkr.ecr.cn-north-1.amazonaws.com.cn/aws-efs-csi-driver",
namespace="xxx",
values={
},
)
由于cdk 2.27.0版本不支持中国区ECR地址解析,还需要手动修改Lambda代码才能正常跑通,新版本可能会做相应适配,即可省去这个步骤。
具体操作为先执行 cdk synth
找到以下路径文件 cdk.out/asset.<random string>/helm/__init__.py
并将其中的“amazonaws.com”替换为“amazonaws.com.cn“,再执行 cdk deploy 即可。
2. 3 手动Pull & Push Helm Chart到Global Public ECR
操作同2. 2类似,语法稍有修改
aws ecr-public create-repository --repository-name <chart_name>
aws ecr-public get-login-password \
--region us-east-1 | helm registry login \
--username AWS \
--password-stdin public.ecr.aws
helm chart save <chart_name>.tgz public.ecr.aws/<random_string>/<chart_name>:<version>
helm chart push public.ecr.aws/<random_string>/<chart_name>:<version>
且cdk代码也需要做相应修改
执行 cdk synth
找到以下路径文件cdk.out/asset.<random string>/helm/__init__.py
line 111: cmnd = ['HELM_EXPERIMENTAL_OCI=1', 'helm', 'pull', repository, '—version', version, '—untar']
line 126: output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, env=env, shell=True)
2. 4 总结
由于CDK代码对中国区适配不佳,方法2. 2与2. 3略显复杂,建议采用2. 1作为解决方案,但2. 1的弊端在于无法对Helm Chart做版本管理,未来可根据CDK的更新内容采用不同解决方案。
3. Helm Chart 所依赖的特定Image无法访问解决方案
这里以通过CDK安装“jupyter-hub” Helm Chart为例,以下代码在Global Region测试通过
jupyterhub_chart = eks_cluster.add_helm_chart(
"jupyterhub-chart",
chart="jupyterhub",
version="1.2.0",
release="jupyterhub",
repository="https://jupyterhub.github.io/helm-chart",
create_namespace=True,
namespace="jupyter-hub",
values=k8s_values,
)
在中国区运行 cdk deploy 出现以下报错信息,可以确认为无法访问Helm Chart所依赖的Image
下午9:59:34 | CREATE_FAILED | Custom::AWSCDK-EKS-HelmChart | addftestjupyrerhub...erhubchart8C4E93E9
Received response status [FAILED] from custom resource. Message returned: Error: b'Release "jupyterhub" does not exist. Installing it now.\nError:
failed pre-install: timed out waiting for the condition\n'
本地连接EKS Cluster
aws sts assume-role —role-arn arn:aws-cn:iam::<account-id>:role/<eks-cluster-master-role> —role-session-name aws-auth-ops | jq -r ‘.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"'
export AWS_ACCESS_KEY_ID=<access-key>
export AWS_SECRET_ACCESS_KEY=<secret-key>
export AWS_SESSION_TOKEN=<session-token>
aws eks update-kubeconfig --name <eks-cluster-name>
运行以下指令查看EKS log,定位具体是哪个Image执行pull的时候失败
kubectl -n jupyter-hub get events --sort-by='{.lastTimestamp}'
可以找到报错信息如下
60m Warning Failed pod/hook-image-puller-qxcpj Failed to pull image "k8s.gcr.io/pause:3.5": rpc error: code = Unknown desc = Error response from daemon: Get "https://k8s.gcr.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
可以采取手动的方式,或者根据这篇博客提供的方法,将相应Image批量上传到中国区ECR
https://aws.amazon.com/cn/blogs/china/convenient-and-safe-use-of-overseas-public-container-images-in-aws-china/
并根据Helm Chart values的schema将Image地址做替换
具体操作为,在Helm Chart目录下values.yaml文件中,找到下载失败的Image位置,本文案例中为”k8s.gcr.io/pause:3.5“
prePuller:
pause:
image:
name: k8s.gcr.io/pause
tag: "3.5"
在CDK的add_helm_chart中根据values的schema添加values参数,替换掉相应Image地址,即可正常执行 cdk deploy
chart = eks_cluster.add_helm_chart(
"jupyterhub-chart",
chart="jupyterhub",
version="1.2.0",
release="jupyterhub",
repository="https://jupyterhub.github.io/helm-chart",
create_namespace=True,
namespace="jupyter-hub",
values={
"prePuller": {
"pause": {
"image": {
"name": "<account-id>.dkr.ecr.cn-north-1.amazonaws.com.cn/pause"
}
}
},
},
)
4. 总结
目前CDK对于在中国区安装EKS Helm Chart支持尚不完善,通过本文,你可以了解一些解决方案,来实现通过CDK部署相应Helm Chart。
参考资料:
CDK Python Document – https://docs.aws.amazon.com/cdk/api/v1/python/
Helm Command Document – https://helm.sh/docs/helm/
在 AWS 中国区方便安全的使用海外公开容器镜像 – https://aws.amazon.com/cn/blogs/china/convenient-and-safe-use-of-overseas-public-container-images-in-aws-china/
Push Helm Chart to ECR – https://docs.aws.amazon.com/zh_cn/AmazonECR/latest/userguide/push-oci-artifact.html
本篇作者