Browse Source

Add CloudFront, add ability to read key file for production

Anuj Bansal 3 years ago
parent
commit
898a82e658

+ 0 - 11
devops/infrastructure/kubernetes/Pulumi.dev.yaml

@@ -1,11 +0,0 @@
-encryptionsalt: v1:kqdIgrY7tCI=:v1:rR0N31Qa+qhxZjqQ:Xlxmi2hMyUFDXZ/T9T5WddJPFZsMZA==
-config:
-  aws:profile: joystream-user
-  aws:region: us-east-1
-  eks-cluster:isProduction: 'true'
-  eks-cluster:keyFile: PATH
-  eks-cluster:passphrase:
-    secure: v1:Qxeuju3X9BgnL59p:/NH8z1BlrmJWLJX8oM6BoD1IxUb153+tQkQ=
-  eks-cluster:providerId: ID
-  eks-cluster:publicURL: DOMAIN
-  eks-cluster:wsProviderEndpointURI: wss://18.209.241.63.nip.io/

+ 1 - 0
devops/infrastructure/kubernetes/.gitignore → devops/infrastructure/storage-node/.gitignore

@@ -2,3 +2,4 @@
 /node_modules/
 kubeconfig.yml
 package-lock.json
+Pulumi.*.yaml

+ 1 - 1
devops/infrastructure/kubernetes/Pulumi.yaml → devops/infrastructure/storage-node/Pulumi.yaml

@@ -16,7 +16,7 @@ template:
     providerId:
       description: StorageProviderId assigned to you in working group
     keyFile:
-      description: JSON key export file to use as the storage provider (role account)
+      description: Path to JSON key export file to use as the storage provider (role account)
     publicURL:
       description: API Public URL to announce
     passphrase:

+ 0 - 0
devops/infrastructure/kubernetes/README.md → devops/infrastructure/storage-node/README.md


+ 80 - 6
devops/infrastructure/kubernetes/index.ts → devops/infrastructure/storage-node/index.ts

@@ -1,7 +1,9 @@
 import * as awsx from '@pulumi/awsx'
+import * as aws from '@pulumi/aws'
 import * as eks from '@pulumi/eks'
 import * as k8s from '@pulumi/kubernetes'
 import * as pulumi from '@pulumi/pulumi'
+import * as fs from 'fs'
 
 const awsConfig = new pulumi.Config('aws')
 const config = new pulumi.Config()
@@ -29,13 +31,13 @@ export const kubeconfig = cluster.kubeconfig
 const repo = new awsx.ecr.Repository('colossus-image')
 
 // Build an image and publish it to our ECR repository.
-
 export const colossusImage = repo.buildAndPushImage({
   dockerfile: '../../../colossus.Dockerfile',
   context: '../../../',
 })
 
 const name = 'storage-node'
+const colossusPort = 3001
 
 // Create a Kubernetes Namespace
 const ns = new k8s.core.v1.Namespace(name, {}, { provider: cluster.provider })
@@ -55,7 +57,7 @@ const service = new k8s.core.v1.Service(
     },
     spec: {
       type: 'LoadBalancer',
-      ports: [{ name: 'port-1', port: 3001 }],
+      ports: [{ name: 'port-1', port: colossusPort }],
       selector: appLabels,
     },
   },
@@ -66,24 +68,50 @@ const service = new k8s.core.v1.Service(
 
 // Export the Service name and public LoadBalancer Endpoint
 export const serviceName = service.metadata.name
-// When "done", this will print the public IP.
+// When "done", this will print the hostname
 export let serviceHostname: pulumi.Output<string>
 serviceHostname = service.status.loadBalancer.ingress[0].hostname
-const publicUrlInput: pulumi.Input<string> = pulumi.interpolate`http://${serviceHostname}:${3001}/`
+
+const publicUrlInput: pulumi.Input<string> = pulumi.interpolate`http://${serviceHostname}:${colossusPort}/`
 
 let additionalParams: string[] | pulumi.Input<string>[] = []
 
+let volumeMounts: pulumi.Input<pulumi.Input<k8s.types.input.core.v1.VolumeMount>[]> = []
+let volumes: pulumi.Input<pulumi.Input<k8s.types.input.core.v1.Volume>[]> = []
+
 if (isProduction) {
+  const remoteKeyFilePath = '/joystream/key-file.json'
   const providerId = config.require('providerId')
   const keyFile = config.require('keyFile')
   const publicUrl = config.get('publicURL') ? config.get('publicURL')! : publicUrlInput
 
-  additionalParams = ['--provider-id', providerId, '--key-file', keyFile, '--public-url', publicUrl]
+  const keyConfig = new k8s.core.v1.ConfigMap(name, {
+    metadata: { namespace: namespaceName, labels: appLabels },
+    data: { 'fileData': fs.readFileSync(keyFile).toString() },
+  })
+  const keyConfigName = keyConfig.metadata.apply((m) => m.name)
+
+  additionalParams = ['--provider-id', providerId, '--key-file', remoteKeyFilePath, '--public-url', publicUrl]
+
+  volumeMounts.push({
+    mountPath: remoteKeyFilePath,
+    name: 'keyfile-volume',
+    subPath: 'fileData',
+  })
+
+  volumes.push({
+    name: 'keyfile-volume',
+    configMap: {
+      name: keyConfigName,
+    },
+  })
 
   const passphrase = config.get('passphrase')
   if (passphrase) {
     additionalParams.push('--passphrase', passphrase)
   }
+} else {
+  additionalParams.push('--anonymous')
 }
 
 // Create a Deployment
@@ -113,6 +141,7 @@ const deployment = new k8s.apps.v1.Deployment(
                 'set -e; \
                 /usr/local/bin/start_ipfs config profile apply lowpower; \
                 /usr/local/bin/start_ipfs config --json Gateway.PublicGateways \'{"localhost": null }\'; \
+                /usr/local/bin/start_ipfs config Datastore.StorageMax 200GB; \
                 /sbin/tini -- /usr/local/bin/start_ipfs daemon --migrate=true',
               ],
             },
@@ -130,10 +159,10 @@ const deployment = new k8s.apps.v1.Deployment(
                   value: 'joystream:*',
                 },
               ],
+              volumeMounts,
               command: [
                 'yarn',
                 'colossus',
-                '--anonymous',
                 '--ws-provider',
                 wsProviderEndpointURI,
                 '--ipfs-host',
@@ -143,6 +172,7 @@ const deployment = new k8s.apps.v1.Deployment(
               ports: [{ containerPort: 3001 }],
             },
           ],
+          volumes,
         },
       },
     },
@@ -154,3 +184,47 @@ const deployment = new k8s.apps.v1.Deployment(
 
 // Export the Deployment name
 export const deploymentName = deployment.metadata.name
+
+// Create a CloudFront distribution
+const distributionArgs: aws.cloudfront.DistributionArgs = {
+  enabled: true,
+  origins: [
+    {
+      originId: 'storage-node-load-balancer',
+      domainName: serviceHostname,
+      customOriginConfig: {
+        originProtocolPolicy: 'http-only',
+        httpPort: colossusPort,
+        httpsPort: colossusPort,
+        originSslProtocols: ['TLSv1'],
+      },
+    },
+  ],
+
+  defaultCacheBehavior: {
+    targetOriginId: 'storage-node-load-balancer',
+
+    viewerProtocolPolicy: 'allow-all',
+    allowedMethods: ['GET', 'HEAD'],
+    cachedMethods: ['GET', 'HEAD'],
+
+    forwardedValues: {
+      cookies: { forward: 'none' },
+      queryString: false,
+    },
+  },
+
+  restrictions: {
+    geoRestriction: {
+      restrictionType: 'none',
+    },
+  },
+
+  viewerCertificate: {
+    cloudfrontDefaultCertificate: true,
+  },
+}
+
+const cloudfront = new aws.cloudfront.Distribution(`storage-node`, distributionArgs)
+
+export const cloudFrontDomain = cloudfront.domainName

+ 0 - 0
devops/infrastructure/kubernetes/package.json → devops/infrastructure/storage-node/package.json


+ 0 - 0
devops/infrastructure/kubernetes/tsconfig.json → devops/infrastructure/storage-node/tsconfig.json