跳转至

ExternalDNS for Route53

func create hosted zone

install

install-with-eksdemo-

install-

  • https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md
  • 创建所需要的服务账号 (create service account)
    • 确保 EKS 集群名称正确 (ensure eks cluster name is correct)
    • 确保使用正确的 Region (ensure region is correct)
    • 确保域名匹配所需 (ensure domain name is correct)
      CLUSTER_NAME=ekscluster1
      AWS_REGION=us-west-2
      DOMAIN_NAME=poc1207.xxx.xxx.xxx
      EXTERNALDNS_NS=externaldns
      export AWS_PAGER=""
      
      # create namespace if it does not yet exist
      kubectl get namespaces | grep -q $EXTERNALDNS_NS || \
        kubectl create namespace $EXTERNALDNS_NS
      
      cat >externaldns-policy.json <<-EOF
      {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "route53:ChangeResourceRecordSets"
            ],
            "Resource": [
              "arn:aws:route53:::hostedzone/*"
            ]
          },
          {
            "Effect": "Allow",
            "Action": [
              "route53:ListHostedZones",
              "route53:ListResourceRecordSets"
            ],
            "Resource": [
              "*"
            ]
          }
        ]
      }
      EOF
      
      POLICY_NAME=AllowExternalDNSUpdates-${RANDOM}
      aws iam create-policy --policy-name ${POLICY_NAME} --policy-document file://externaldns-policy.json
      
      # example: arn:aws:iam::XXXXXXXXXXXX:policy/AllowExternalDNSUpdates
      export POLICY_ARN=$(aws iam list-policies \
       --query 'Policies[?PolicyName==`'"${POLICY_NAME}"'`].Arn' --output text)
      
      eksctl create iamserviceaccount \
        --cluster ${CLUSTER_NAME} \
        --name "external-dns" \
        --namespace ${EXTERNALDNS_NS:-"default"} \
        --override-existing-serviceaccounts \
        --attach-policy-arn $POLICY_ARN \
        --approve
      

HELM INSTALL

echo ${EXTERNALDNS_NS}

helm repo add --force-update external-dns https://kubernetes-sigs.github.io/external-dns/

# support gateway api
cat >externaldns-values.yaml <<-EOF
sources:

  - service
  - ingress
  - gateway-httproute
  - gateway-tcproute
EOF

helm upgrade --install external-dns external-dns/external-dns \
  --namespace ${EXTERNALDNS_NS:-"default"} \
  --set serviceAccount.create=false \
  --set serviceAccount.name=external-dns \
  -f externaldns-values.yaml

MANUAL INSTALL – 使用上述服务账号安装 ExternalDNS (install ExternalDNS with existed SA)

echo ${EXTERNALDNS_NS}
echo ${DOMAIN_NAME}
echo ${AWS_REGION}

envsubst >externaldns-with-rbac.yaml <<-EOF
# comment out sa if it was previously created
# apiVersion: v1
# kind: ServiceAccount
# metadata:
#   name: external-dns
#   labels:
#     app.kubernetes.io/name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: external-dns
  labels:
    app.kubernetes.io/name: external-dns
rules:

  - apiGroups: [""]
    resources: ["services","endpoints","pods","nodes"]
    verbs: ["get","watch","list"]
  - apiGroups: ["extensions","networking.k8s.io"]
    resources: ["ingresses"]
    verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
  labels:
    app.kubernetes.io/name: external-dns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
  - kind: ServiceAccount
    name: external-dns
    namespace: ${EXTERNALDNS_NS} # change to desired namespace: externaldns, kube-addons
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
  labels:
    app.kubernetes.io/name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app.kubernetes.io/name: external-dns
  template:
    metadata:
      labels:
        app.kubernetes.io/name: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
        - name: external-dns
          image: registry.k8s.io/external-dns/external-dns:v0.13.2
          args:
            - --source=service
            - --source=ingress
            - --domain-filter=${DOMAIN_NAME} # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
            - --provider=aws
            - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
            - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
            - --registry=txt
            - --txt-owner-id=external-dns
          env:
            - name: AWS_DEFAULT_REGION
              value: ${AWS_REGION} # change to region where EKS is installed
     # # Uncommend below if using static credentials
     #        - name: AWS_SHARED_CREDENTIALS_FILE
     #          value: /.aws/credentials
     #      volumeMounts:
     #        - name: aws-credentials
     #          mountPath: /.aws
     #          readOnly: true
     #  volumes:
     #    - name: aws-credentials
     #      secret:
     #        secretName: external-dns
EOF

kubectl create --filename externaldns-with-rbac.yaml \
  --namespace ${EXTERNALDNS_NS:-"default"}

sample

verify-

  • create namespace
    NS=verify
    kubectl create ns ${NS}
    

service sample

  • create nlb (no more clb, 20230423) with service definition

    echo ${DOMAIN_NAME}
    
    envsubst >verify-nginx.yaml <<-EOF
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      annotations:
        external-dns.alpha.kubernetes.io/hostname: nginx.${DOMAIN_NAME}
        service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
    spec:
      type: LoadBalancer
      ports:
    
      - port: 80
        name: http
        targetPort: 80
      selector:
        app: nginx
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: nginx
            name: nginx
            ports:
            - containerPort: 80
              name: http
    EOF
    
    kubectl create --filename verify-nginx.yaml -n ${NS:-default}
    

  • wait nlb available and execute

    aws route53 list-resource-record-sets --output json --hosted-zone-id $ZONE_ID \
      --query "ResourceRecordSets[?Name == 'nginx.${DOMAIN_NAME}.']|[?Type == 'A']"
    
    aws route53 list-resource-record-sets --output json --hosted-zone-id $ZONE_ID \
      --query "ResourceRecordSets[?Name == 'nginx.${DOMAIN_NAME}.']|[?Type == 'TXT']"
    
    dig +short nginx.${DOMAIN_NAME}. A
    
    curl http://nginx.${DOMAIN_NAME}
    

ingress sample

  • ensure certificate is existed and create alb

    echo ${CERTIFICATE_ARN}
    
    envsubst >verify-nginx-ingress.yaml <<-EOF
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/tags: Environment=dev,Team=test,Application=nginx
        alb.ingress.kubernetes.io/target-type: ip
        alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
        alb.ingress.kubernetes.io/ssl-redirect: '443'
        alb.ingress.kubernetes.io/certificate-arn: ${CERTIFICATE_ARN}
    spec:
      ingressClassName: alb
      rules:
    
        - host: server.${DOMAIN_NAME}
          http:
            paths:
              - backend:
                  service:
                    name: nginx
                    port:
                      number: 80
                path: /
                pathType: Prefix
    EOF
    
    kubectl create --filename verify-nginx-ingress.yaml -n ${NS:-default}
    

  • wait alb available and execute

    aws route53 list-resource-record-sets --output json --hosted-zone-id $ZONE_ID \
      --query "ResourceRecordSets[?Name == 'server.${DOMAIN_NAME}.']"
    
    dig +short server.${DOMAIN_NAME}. A
    
    curl https://server.${DOMAIN_NAME}