hello friends. I have a basic EKS service set up u...
# aws
r
hello friends. I have a basic EKS service set up using the typescript example. What's the shortest way to get a certificate and route53 domain associated with the service ip?
b
hey! easiest way is to install the aws provider with
npm install
and then pass the service ip to a route53 record https://www.pulumi.com/docs/reference/pkg/aws/route53/record/ and an ACM certificate https://www.pulumi.com/docs/reference/pkg/aws/acm/certificate/
r
thanks, I managed to get it working in the console using A record and the ALIAS, I'll try to use your suggestions with those settings and see how it works 🙂
I managed to set up the record correctly but I can't seem to get the certificate to work. Always have this error: SSL_ERROR_RX_RECORD_TOO_LONG
no idea why this certificate keeps reporting that error, no matter what configuration I try to use the certificate always seems to result in this RX too long error
b
can you share your code?
r
Copy code
const repository = new awsx.ecr.Repository(`${pkg.name}-repo`);

// // Invoke 'docker' to actually build the DockerFile that is in the 'app' folder relative to
// // this program. Once built, push that image up to our personal ECR repo.
const image = repository.buildAndPushImage({
  dockerfile: "../apps/dedicated-game-server/Dockerfile",
  context: "../",
  cacheFrom: true,
});

// Create a VPC for our cluster.
const vpc = new awsx.ec2.Vpc("vpc", { numberOfAvailabilityZones: 2 });

// Create the EKS cluster itself and a deployment of the Kubernetes dashboard.
const cluster = new eks.Cluster("cluster", {
  vpcId: vpc.id,
  subnetIds: vpc.publicSubnetIds,
  desiredCapacity: 1,
  minSize: 1,
  maxSize: 1,
});

// Create a NGINX Deployment and load balanced Service, running our app.
const appName = "kennywtf";
const appLabels = { appClass: appName };
const deployment = new k8s.apps.v1.Deployment(
  `${appName}-dep`,
  {
    metadata: { labels: appLabels },
    spec: {
      replicas: 1,
      selector: { matchLabels: appLabels },
      template: {
        metadata: { labels: appLabels },
        spec: {
          containers: [
            {
              name: appName,
              image,
              ports: [{ name: "http", containerPort: 8999 }],
            },
          ],
        },
      },
    },
  },
  { provider: cluster.provider }
);

const service = new k8s.core.v1.Service(
  `${appName}-svc`,
  {
    metadata: { labels: appLabels },
    spec: {
      type: "LoadBalancer",
      ports: [
        { port: 80, targetPort: "http", name: "http" },
        { port: 443, targetPort: "http", name: "https" },
      ],
      selector: appLabels,
    },
  },
  { provider: cluster.provider }
);

const certificate = new aws.acm.Certificate("sslCert", {
  domainName,
  subjectAlternativeNames: [],
  validationMethod: "DNS",
});

// Create the necessary DNS records for ACM to validate ownership, and wait for it.
const sslCertValidationRecord = new aws.route53.Record(
  "sslCertValidationRecord",
  {
    zoneId: hostedZoneId,
    name: certificate.domainValidationOptions[0].resourceRecordName,
    type: certificate.domainValidationOptions[0].resourceRecordType,
    records: [certificate.domainValidationOptions[0].resourceRecordValue],
    ttl: 10 * 60 /* 10 minutes */,
  }
);

const sslCertValidationIssued = new aws.acm.CertificateValidation(
  "sslCertValidationIssued",
  {
    certificateArn: certificate.arn,
    validationRecordFqdns: [sslCertValidationRecord.fqdn],
  }
);
const main = aws.elb.getHostedZoneId({});

const webDnsRecord = new aws.route53.Record(
  "webDnsRecord",
  {
    name: domainName,
    type: "A",
    zoneId: hostedZoneId,
    aliases: [
      {
        evaluateTargetHealth: true,
        name: service.status.loadBalancer.ingress[0].hostname,
        zoneId: main.then((main) => main.id),
      },
    ],
  },
  { dependsOn: sslCertValidationIssued }
);

// // Export the URL for the load balanced service.

export const url = service.status.loadBalancer.ingress[0].hostname;
export const ip = service.status.loadBalancer.ingress[0].ip;
like I said, it deploys great and the domain points correctly to the service (kenny.wtf) but the cert doesnt seem to work. In the ACM dashboard the cert says
in use: no
which is strange to me
So, after playing around, I found that I can find the load balancer inside the EC2 management console. There, I was able to change the settings from TCP to secure TCP, and chose an ARN for a certificate I had made with pulumi
Now the question is, how do I automate that with pulumi...
b
hey! can you show me where you get
domainName
from?
does your cert have the right name when you look at it in the console?
r
domainName is just a string, I get it from the pulumi config
uhhh, yeah the cert has the right name
and now that I've manually attached it to this classic loadbalancer that I think was created when I made the k8s service, it finally says
in use: yes
so it looks like I can't just simply use the service loadbalancer output to attach a certificate alias to, that didn't work...
b
you mean the
<http://amazonaws.com|amazonaws.com>
name your ELB has?
r
I'm still not clear what the problem is, but something about connecting that domain, the cert, and the loadbalancer that is outputted from that k8s service doesnt click for https
it didnt work until I dug around the aws console manually and connected the cert to the classic loadbalancer manually
I followed this step to get it to work (starting from step 10, it was a complete hail mary): https://aws.amazon.com/premiumsupport/knowledge-center/terminate-https-traffic-eks-acm/
b
okay, I see what's happening here
here:
Copy code
const webDnsRecord = new aws.route53.Record(
  "webDnsRecord",
  {
    name: domainName,
    type: "A",
    zoneId: hostedZoneId,
    aliases: [
      {
        evaluateTargetHealth: true,
        name: service.status.loadBalancer.ingress[0].hostname,
        zoneId: main.then((main) => main.id),
      },
    ],
  },
  { dependsOn: sslCertValidationIssued }
);
you're creating an A record to your
service.status.loadBalancer.ingress[0].hostname
- make this a
CNAME
, not an
A
record
update your validationRecord to use an apply, example:
Copy code
validationRecordFqdns: sslCertValidationRecord.apply(r => r.map(record => record.fqdn))
(I think, I haven't tested this)