在Ingress上终止TLS

本节我们研究需要在Ingress终止 TLS 的场景。

对于此场景,流量源自客户端(例如终端用户的笔记本电脑)并终止于应用程序运行的 Ingress controller(我们将在EKS 上设置 NGINX ingress controller)。

安装 NGINX Ingress 并设置负载ELB

NGINX Ingress 是Ingress 的一种实现方式,使用ConfigMap 存储 NGINX 配置。

使用以下命令安装 NGINX Ingress:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/aws/deploy.yaml

image-20231203175513291

NLB可能需要 3-5 分钟才能激活 - 可以通过到 EC2 控制台检查进度, 应当看到NLB处于Active状态:

image-20231203175717600

运行以下命令以确定 AWS 分配给 NLB 的地址:

kubectl get service -n ingress-nginx

External IP中列出NLB的 DNS 名称:

image-20231203175828194

向 AWS Private CA 请求证书

现在,可以开始从所配置的Issuer向Private CA请求可供 Kubernetes 应用程序使用的证书

第一步,创建一个命名空间:

kubectl create namespace acm-pca-lab-demo

接下来创建基本的 X.509 私有证书, 创建一个名为eks-cert.yaml的文件,内容如下:

kind: Certificate
apiVersion: cert-manager.io/v1
metadata:
  name: eks-cert
  namespace: acm-pca-lab-demo
spec:
# You can put any common name here as long as the DNS name for NLB is in the below section
  commonName: eks-example-domain
  dnsNames:
  # 确保替换为NLB DNS
    - a4d216f11fc0b4a8e8ccf72ecb2b2029-380528a4bc75a3e5.elb.us-west-2.amazonaws.com
  duration: 2160h0m0s
  issuerRef:
    group: awspca.cert-manager.io
    kind: AWSPCAClusterIssuer
    name: demo-test-root-ca
  renewBefore: 360h0m0s
  secretName: eks-example-cert
  usages:
    - server auth
    - client auth
  privateKey:
    algorithm: "RSA"
    size: 2048

上面使用 RSA 2048 密钥算法颁发证书,创建资源:

kubectl apply -f eks-cert.yaml -n acm-pca-lab-demo

通过运行以下命令验证证书是否已颁发且处于 READY 状态:

kubectl get certificate -n acm-pca-lab-demo

image-20231203180704763

一旦证书状态显示为已颁发,可以使用以下命令查看已颁发的证书详细信息:

kubectl get secret eks-example-cert -n acm-pca-lab-demo -o 'go-template={{index .data "tls.crt"}}' | base64 --decode | openssl x509 -noout -text

image-20231203181027763

部署应用

创建一个简单的“hello world”网站服务,它通过判断HTTP 请求标头,以及返回一些集群详细信息进行响应。

创建hello-world.yaml


apiVersion: v1
kind: Service
metadata:
  name: hello-world
  namespace: acm-pca-lab-demo
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-world
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
  namespace: acm-pca-lab-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: echoheaders
        image: k8s.gcr.io/echoserver:1.10
        args:
        - "-text=Hello World"
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 8080

使用以下命令创建服务:

kubectl apply -f hello-world.yaml

我们已经颁发了证书并部署了应用,现在使用 Ingress 将应用暴露出来

创建一个名为example-ingress.yaml的文件并添加以下内容,将tls:hostsRules:host下的 NLB DNS 名称替换为自己的 NLB DNS:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: acm-pca-lab-demo
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - a4d216f11fc0b4a8e8ccf72ecb2b2029-380528a4bc75a3e5.elb.us-west-2.amazonaws.com
    secretName: eks-example-cert
  rules:
  - host: a4d216f11fc0b4a8e8ccf72ecb2b2029-380528a4bc75a3e5.elb.us-west-2.amazonaws.com
    http:
      paths:
      - path: /
        pathType: Exact
        backend:
          service:
            name: hello-world
            port:
              number: 80

通过运行以下命令创建新的 Ingress 资源:

# 如果遇到报错,可能要执行以下命令: kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
# 参考 https://stackoverflow.com/questions/61365202/nginx-ingress-service-ingress-nginx-controller-admission-not-found
kubectl apply -f example-ingress.yaml

验证TLS

使用NLB地址访问,结果如下(因为我们之前已经在浏览器中信息了根CA,所以可以正常访问):

image-20231203224201580

如果浏览器没有信任根CA,会显示:

image-20231203224535922