AWS ACM 如何与 Kubernetes 配合使用?

API
Kubernetes
0
0
>作者容鑫,API7.ai 云原生技术工程师,Apache APISIX Committer。 ## **为什么需要 AWS ACM ?** ### **手动管理证书带来的问题** 证书包含持有者、颁发者、失效日期等信息。为了确保证书能够被安全地使用,同时也确保证书能够被及时吊销和续订,证书的相关信息需要被记录下来,例如可以手动记录到电子表格中。 但随着管理的证书越来越多,手动管理的方式容易因遗漏而导致证书中断,它无法根据新信息和法规自动更新。因为证书到期之前电子表格不会通知你,也不会自动为即将到期的证书续订。手动管理的方式不可避免会操作失误,这将为你带来不必要的风险。这时,自动管理证书的方式应运而生,它将减少人为操作的工作负担和相关风险。 ### **ACM 自动管理证书** [AWS Certificate Manager](https://aws.amazon.com/cn/certificate-manager/?trk=cndc-detail)(ACM) 可以轻松预置、管理、部署和续订 SSL/TLS 证书。你可以直接通过 ACM 签发证书保护你的 AWS 网站和应用程序,或者将第三方证书导入 ACM 管理系统中。使用 ACM,你无需经历过去与使用和管理 SSL/TLS 证书相关的大量手动流程,还可以导出由 AWS Private CA 签名的 ACM 证书,以便在内部 PKI 中的任何位置使用。同时它还集成了 AWS [Elastic Load Balancing](https://aws.amazon.com/cn/elasticloadbalancing/?trk=cndc-detail)(ELB)。 ![download_image.jpeg](https://dev-media.amazoncloud.cn/8013210677de49a18162ffa77f0b84e3_download_image.jpeg "download_image.jpeg") ## **ACM Private CA 解决了哪些问题?** 当组织中没有任何 Private CA,在部署内部应用程序时,他们都使用了自签名证书。这些应用程序相互访问时,由于对方的不受信任而拒绝访问,如果盲目信任未知来源的应用程序会带来安全风险。这就需要有一个 Private CA 的托管服务,负责创建和管理 CA 层次结构,确保组织内的应用程序之间是受信任的。 ACM Private CA 就是一种高可用的托管服务,用于为你的组织创建和维护内部公钥基础设施,消除了持续维护的成本。私钥存储在经过 FIPS 140-2 认证的 AWS 托管硬件安全模块 (HSM) 中。与 Kubernetes 中的默认 CA 相比,提供更安全的证书颁发机构解决方案。 ![download_image (9).png](https://dev-media.amazoncloud.cn/87cced5645cd45febf42b03656ed3384_download_image%20%289%29.png "download_image (9).png") ## **如何与 Kubernetes 配合使用?** ![image (29).png](https://dev-media.amazoncloud.cn/6db5e2bdcd094418bafab5303093b40d_image%20%2829%29.png "image (29).png") 在 Kubernetes 中终止 TLS 证书有两种配置方式: * **在 NLB 终止**:对于一些使用公开信任的证书,在 NLB 级别终止 TLS 证书是最常见的用例。此方式易于配置,将 ACM 公开信任证书绑定到 NLB。集群内部进行应用的访问依然用的是 HTTP 访问方式,无需额外的加解密运算。 * **在 Ingress 终止**: 当应用之间有加密需求,需要在 Ingress controller 中终止 TLS 。每个应用都可以通过 Ingress 管理自己的证书,互不干扰,能够保证应用之间的通信是受信任的,此方式更易于配置和管理。 在接下来的演示示例中,将会在 [Amazon EKS](https://aws.amazon.com/cn/eks/?trk=cndc-detail) 上设置 APISIX Ingress,我们会根据这两种方式演示 APISIX Ingress 如何与 ACM 配合使用(以及 ACM Private CA)。 ## **准备:预置环境** 开始之前,你需要具备以下条件: * [AWS](https://signin.aws.amazon.com/signin?redirect_uri=https://portal.aws.amazon.com/billing/signup/resume&client_id=signup) 账号与 [AWS 命令行界面](https://aws.amazon.com/cn/cli/?trk=cndc-detail)[(AWS CLI)](http://aws.amazon.com/cli)。 * 你必须有权使用 [Amazon EKS](https://aws.amazon.com/cn/eks/?trk=cndc-detail) IAM 角色和服务相关角色、[AWS CloudFormation](http://aws.amazon.com/cloudformation)、[Amazon Virtual Private Cloud (Amazon VPC)](http://aws.amazon.com/vpc)和相关资源。请参阅 IAM 用户指南中的[适用于 Kubernetes 的 Amazon Elastic Container Service 的操作、资源和条件键](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelastickubernetesservice.html)以及使用[服务相关角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html)。此外,此 IAM 安全主体需要附加一个 AWSCertificateManagerPrivateCAFullAccess IAM 托管策略。 * 安装并配置了 **kubectl** 和 [eksctl](https://docs.aws.amazon.com/zh_en/eks/latest/userguide/getting-started-eksctl.html) 工具。 ### **Amazon EKS 集群** [Amazon EKS](https://aws.amazon.com/cn/eks/?trk=cndc-detail) 是一种托管服务,你可以使用它在 AWS 上运行 Kubernetes,轻松地部署和管理你的 Kubernetes 集群。本文将使用 eksctl 命令工具来管理集群,这里使用 eksctl 默认配置创建集群(如果你已有 EKS 集群请忽略): ```bash eksctl create cluster ``` ### **安装 APISIX Ingress** 第一步,在 EKS 集群中安装 APISIX Ingress,并设置为 LoadBalancer 类型。 ```plain helm repo add apisix https://charts.apiseven.com helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update helm install apisix apisix/apisix \\ --set gateway.type=LoadBalancer \\ --set gateway.tls.enabled=true \\ --set ingress-controller.enabled=true \\ --namespace ingress-apisix \\ --create-namespace ``` 需注意:请确保你的集群能够添加持久性卷,详情请参阅 [Amazon EKS Storage](https://docs.aws.amazon.com/zh_en/eks/latest/userguide/storage.html)。 如果只是为了体验本教程,需要在安装时配置 `--set etcd.persistence.enabled=false` 声明不使用持久性卷。 第二步,运行以下命令检查状态,确保全部 Pod 处于 Running。 ```plain \$ kubectl get pods -n ingress-apisix NAME READY STATUS RESTARTS AGE apisix-78bfc58588-qspmm 1/1 Running 0 103s apisix-etcd-0 1/1 Running 0 103s apisix-etcd-1 1/1 Running 0 103s apisix-etcd-2 1/1 Running 0 103s apisix-ingress-controller-6ff56cd4b4-rktr9 1/1 Running 0 103s ``` 第三步,检查 NLB 状态,这里重点关注 PORT(S) 和 EXTERNAL-IP。 ```plain \$ kubectl get svc apisix-gateway -n ingress-apisix NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE apisix-gateway LoadBalancer 10.100.178.65 a6cffe9f6fc5c47b9929cb758610fc5a-2074689558.ap-northeast-1.elb.amazonaws.com 80:30851/TCP,443:32735/TCP 103s ``` ## **方式一:在 NLB 终止 TLS 证书** ### **准备 ACM 证书** 打开 [ACM 控制台](https://console.aws.amazon.com/acm/home),为你的自定义域申请公共 ACM 证书或导入自定义证书。 ![download_image (1).jpeg](https://dev-media.amazoncloud.cn/e1863c3620544a2dadeff225c0aad82e_download_image%20%281%29.jpeg "download_image (1).jpeg") ### **LoadBalancer 配置证书** 1. 打开 [EC2 控制台](https://console.aws.amazon.com/ec2/),选择你的 **Load Balancers(负载均衡器)** -> **侦听器** -> **edit**。 ![image (32).png](https://dev-media.amazoncloud.cn/cf7adc17664b4f728295442d7f26f5a9_image%20%2832%29.png "image (32).png") 2. NLB 协议设置为 HTTPS,端口 443,实例协议设置为 HTTP,端口 30851。 ![image (33).png](https://dev-media.amazoncloud.cn/ad2537b6a3e140be80dca5caee047323_image%20%2833%29.png "image (33).png") 3. 将 ACM 中的 TLS 证书附加到 NLB。 ![image (34).png](https://dev-media.amazoncloud.cn/fd24a7906f9341978bc1159008b61129_image%20%2834%29.png "image (34).png") ### **将自定义域与负载均衡器名称关联** 你可以使用 DNS 提供商的控制台,通过 CNAME 将应用程序的 DNS 记录指向 NLB 的 URL。例如 [Route53](https://console.aws.amazon.com/route53),[并设置指向你的 NLB 的 CNAME 记录](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/using-domain-names-with-elb.html#dns-associate-custom-elb)。 ```plain httpbin.example-test.org CNAME a6cffe9f6fc5c47b9929cb758610fc5a-2074689558.ap-northeast-1.elb.amazonaws.com ``` ### **访问应用域名** 使用以下命令进行访问: ```shell curl https://httpbin.example-test.org ``` ## **方式二:在 Ingress 终止 TLS 证书** ***在开始本示例前,请确保 AWS NLB 的配置已恢复如下图片所示:*** ![image (35).png](https://dev-media.amazoncloud.cn/9fa51ff7d0d2471cb68eedb4aa3a02f7_image%20%2835%29.png "image (35).png") ### **安装 cert-manager** cert-manager 是一个 Kubernetes 附加组件,可用于自动管理和颁发来自各种颁发来源的 TLS 证书,你可以在常规方式[安装 cert-manager](https://cert-manager.io/docs/installation/helm/)。 ### **创建 ACM Private CA** 1. 打开 ACM PCA 控制台,选择创建证书,并安装。 ![image (36).png](https://dev-media.amazoncloud.cn/979b90845c0e42f19cfe64fe278a2244_image%20%2836%29.png "image (36).png") 2. 在 CA 成功创建后,状态为 active,其中 PCA 的 **ARN** 将会在后续流程中多次使用。 ![download_image (2).jpeg](https://dev-media.amazoncloud.cn/1e5af0cd86d34808b6b61f89e2156adc_download_image%20%282%29.jpeg "download_image (2).jpeg") ### **为 ACM Private CA 设置 EKS 节点权限** 默认情况下是无颁发权限,为了从 ACM Private CA 颁发证书,需要将 IAM 策略添加到 EKS NodeInstanceRole 中,包括 iamserviceaccount 服务角色。 第一步,创建 `pca-iam-policy.json` 文件,需要将 `\${PCA_ARN}` 替换成你的 PCA_ARN。 ```plain { "Version": "2012-10-17", "Statement": [ { "Sid": "awspcaissuer", "Action": [ "acm-pca:DescribeCertificateAuthority", "acm-pca:GetCertificate", "acm-pca:IssueCertificate" ], "Effect": "Allow", "Resource": "\${PCA_ARN}" } ] } ``` 第二步,根据 `pca-iam-policy.json` 创建 IAM 和 iamserviceaccount,需要将 `\${account_id}` 替换为你的 Amazon 账户ID。 ```plain aws iam create-policy \\ --policy-name AWSPCAIssuerIAMPolicy \\ --policy-document file://pca-iam-policy.json # 创建命名空间 kubectl create namespace aws-pca-issuer eksctl create iamserviceaccount \\ --cluster=\${cluster_name} \\ --namespace=aws-pca-issuer \\ --name=aws-pca-issuer \\ --attach-policy-arn=arn:aws:iam::\${account_id}:policy/AWSPCAIssuerIAMPolicy \\ --override-existing-serviceaccounts \\ --approve ``` ### **安装 aws-privateca-issuer** AWS PrivateCA Issuer 充当 cert-manager 的插件([External Issuers](https://cert-manager.io/docs/configuration/external/))签署证书请求。 1. 使用 Helm 安装 ```plain helm repo add awspca https://cert-manager.github.io/aws-privateca-issuer helm repo update helm install aws-pca-issuer awspca/aws-privateca-issuer \\ -n aws-pca-issuer \\ --set serviceAccount.create=false \\ --set serviceAccount.name=aws-pca-issuer ``` 2. 查看状态 ```plain \$ kubectl get pods -n aws-pca-issuer NAME READY STATUS RESTARTS AGE aws-pca-issuer-aws-privateca-issuer-5cdd4b4687-z52n7 1/1 Running 0 20s ``` ### **创建颁发者并申请证书** 1. 将 issuer-cert.yaml 文件中的 `\${PCA_ARN}` 替换成你的配置,并执行如下命令: `kubectl apply -f issuer-cert.yaml` ```plain # issuer-cert.yaml apiVersion: awspca.cert-manager.io/v1beta1 kind: AWSPCAClusterIssuer metadata: name: demo-test-root-ca spec: arn: \${PCA_ARN} --- kind: Certificate apiVersion: cert-manager.io/v1 metadata: name: nlb-lab-tls-cert spec: commonName: httpbin.example-test.org # 需要替换成您的自定义域名 dnsNames: - httpbin.example-test.org # 需要替换为您的自定义域名 duration: 2160h0m0s issuerRef: group: awspca.cert-manager.io kind: AWSPCAClusterIssuer name: demo-test-root-ca renewBefore: 360h0m0s secretName: nlb-tls-app-secret usages: - server auth - client auth privateKey: algorithm: "RSA" size: 2048 ``` 2. 运行以下命令验证证书是否已颁发,secret 是否已生成。 ```plain \$ kubectl get cert NAME READY SECRET AGE nlb-lab-tls-cert True nlb-tls-app-secret 10s \$ kubectl get secret NAME TYPE DATA AGE nlb-tls-app-secret kubernetes.io/tls 3 8s ``` ### **公开并保护 httpbin 应用程序** [请确保 APISIX Ingress 已成功安装](https://github.com/api7/contents/blob/a13324ce0aedff03b66cad4668340aa413a8ba86/blog/using-apisix-ingress-with-aws-acm.md#%E5%AE%89%E8%A3%85-apisix-ingress) 1. 部署 httpbin 应用程序 ```plain kubectl run httpbin --image kennethreitz/httpbin --port 80 kubectl expose pod httpbin --port 80 ``` 2. 创建 Ingress 以公开并保护 httpbin 应用程序 * `kubectl apply -f ingress-httpbin.yaml` ```plain # ingress-httpbin.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: httpbin-demo-apisix spec: ingressClassName: apisix tls: - hosts: - httpbin.example-test.org secretName: nlb-tls-app-secret rules: - host: httpbin.example-test.org http: paths: - backend: service: name: httpbin port: number: 80 path: / pathType: Prefix ``` 3. 访问应用域名 [请确保你的自定义域已与负载均衡器名称关联](https://github.com/api7/contents/blob/a13324ce0aedff03b66cad4668340aa413a8ba86/blog/using-apisix-ingress-with-aws-acm.md#%E5%B0%86%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9F%9F%E4%B8%8E%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8%E5%90%8D%E7%A7%B0%E5%85%B3%E8%81%94)。 ```bash \$ curl https://httpbin.example-test.org/headers --cacert acm-pca/cacert.pem { "headers": { "Accept": "*/*", "Host": "httpbin.example-test.org", "User-Agent": "curl/7.74.0", "X-Forwarded-Host": "httpbin.example-test.org" } } ``` ## **总结** 本文中通过实践演示了 APISIX Ingress 与 AWS ACM 和 ACM Private CA 组件配合使用,并介绍了在 Kubernetes 中终止 TLS 证书的两种配置方式。在公开信任的证书中,ACM + NLB 的配置方式会更合适。如果应用之间有加密的要求,ACM Private CA 提供了安全性更强的托管服务。希望本文的实践环节能帮助读者在 AWS EKS 集群中更有效配置和管理 TLS 流量。
目录
亚马逊云科技解决方案 基于行业客户应用场景及技术领域的解决方案
联系亚马逊云科技专家
亚马逊云科技解决方案
基于行业客户应用场景及技术领域的解决方案
联系专家
0
目录
关闭