index.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import * as awsx from '@pulumi/awsx'
  2. import * as eks from '@pulumi/eks'
  3. import * as pulumi from '@pulumi/pulumi'
  4. import * as k8s from '@pulumi/kubernetes'
  5. import { configMapFromFile } from './configMap'
  6. import { CaddyServiceDeployment } from './caddy'
  7. import { getSubkeyContainers, getValidatorContainers } from './utils'
  8. const config = new pulumi.Config()
  9. const awsConfig = new pulumi.Config('aws')
  10. const isMinikube = config.getBoolean('isMinikube')
  11. export let kubeconfig: pulumi.Output<any>
  12. export let joystreamAppsImage: pulumi.Output<string>
  13. let provider: k8s.Provider
  14. if (isMinikube) {
  15. provider = new k8s.Provider('local', {})
  16. } else {
  17. // Create a VPC for our cluster.
  18. const vpc = new awsx.ec2.Vpc('joystream-node-vpc', { numberOfAvailabilityZones: 2 })
  19. // Create an EKS cluster with the default configuration.
  20. const cluster = new eks.Cluster('eksctl-node-network', {
  21. vpcId: vpc.id,
  22. subnetIds: vpc.publicSubnetIds,
  23. desiredCapacity: 2,
  24. maxSize: 2,
  25. instanceType: 't2.medium',
  26. providerCredentialOpts: {
  27. profileName: awsConfig.get('profile'),
  28. },
  29. })
  30. provider = cluster.provider
  31. // Export the cluster's kubeconfig.
  32. kubeconfig = cluster.kubeconfig
  33. }
  34. const resourceOptions = { provider: provider }
  35. const name = 'node-network'
  36. // Create a Kubernetes Namespace
  37. // const ns = new k8s.core.v1.Namespace(name, {}, { provider: cluster.provider })
  38. const ns = new k8s.core.v1.Namespace(name, {}, resourceOptions)
  39. // Export the Namespace name
  40. export const namespaceName = ns.metadata.name
  41. const appLabels = { appClass: name }
  42. const jsonModifyConfig = new configMapFromFile(
  43. 'json-modify-config',
  44. {
  45. filePath: 'json_modify.py',
  46. namespaceName: namespaceName,
  47. },
  48. resourceOptions
  49. ).configName
  50. const dataPath = '/subkey-data'
  51. const builderPath = '/builder-data'
  52. const networkSuffix = config.get('networkSuffix') || '8129'
  53. const chainSpecPath = `${builderPath}/chainspec-raw.json`
  54. const numberOfValidators = config.getNumber('numberOfValidators') || 2
  55. const subkeyContainers = getSubkeyContainers(numberOfValidators, dataPath)
  56. const validatorContainers = getValidatorContainers(numberOfValidators, dataPath, builderPath, chainSpecPath)
  57. const deployment = new k8s.apps.v1.Deployment(
  58. name,
  59. {
  60. metadata: {
  61. namespace: namespaceName,
  62. labels: appLabels,
  63. },
  64. spec: {
  65. replicas: 1,
  66. selector: { matchLabels: appLabels },
  67. template: {
  68. metadata: {
  69. labels: appLabels,
  70. },
  71. spec: {
  72. initContainers: [
  73. ...subkeyContainers,
  74. {
  75. name: 'builder-node',
  76. image: 'joystream/node:latest',
  77. command: ['/bin/sh', '-c'],
  78. args: [
  79. `/joystream/chain-spec-builder generate -a ${numberOfValidators} \
  80. --chain-spec-path ${builderPath}/chainspec.json --deployment live \
  81. --endowed 1 --keystore-path ${builderPath}/data >> ${builderPath}/seeds.txt`,
  82. ],
  83. volumeMounts: [
  84. {
  85. name: 'builder-data',
  86. mountPath: builderPath,
  87. },
  88. ],
  89. },
  90. {
  91. name: 'json-modify',
  92. image: 'python',
  93. command: ['python'],
  94. args: ['/scripts/json_modify.py', '--path', `${builderPath}/chainspec.json`, '--prefix', networkSuffix],
  95. volumeMounts: [
  96. {
  97. mountPath: '/scripts/json_modify.py',
  98. name: 'json-modify-script',
  99. subPath: 'fileData',
  100. },
  101. {
  102. name: 'builder-data',
  103. mountPath: builderPath,
  104. },
  105. {
  106. name: 'subkey-data',
  107. mountPath: dataPath,
  108. },
  109. ],
  110. },
  111. {
  112. name: 'raw-chain-spec',
  113. image: 'joystream/node:latest',
  114. command: ['/bin/sh', '-c'],
  115. args: [`/joystream/node build-spec --chain ${builderPath}/chainspec.json --raw > ${chainSpecPath}`],
  116. volumeMounts: [
  117. {
  118. name: 'builder-data',
  119. mountPath: builderPath,
  120. },
  121. ],
  122. },
  123. ],
  124. containers: [
  125. ...validatorContainers,
  126. {
  127. name: 'rpc-node',
  128. image: 'joystream/node:latest',
  129. ports: [
  130. { name: 'rpc-9944', containerPort: 9944 },
  131. { name: 'rpc-9933', containerPort: 9933 },
  132. { name: 'rpc-30333', containerPort: 30333 },
  133. ],
  134. args: [
  135. '--chain',
  136. chainSpecPath,
  137. '--unsafe-rpc-external',
  138. '--unsafe-ws-external',
  139. '--ws-external',
  140. '--rpc-cors',
  141. 'all',
  142. '--pruning',
  143. 'archive',
  144. '--ws-max-connections',
  145. '512',
  146. '--telemetry-url',
  147. 'wss://telemetry.joystream.org/submit/ 0',
  148. '--telemetry-url',
  149. 'wss://telemetry.polkadot.io/submit/ 0',
  150. ],
  151. volumeMounts: [
  152. {
  153. name: 'subkey-data',
  154. mountPath: dataPath,
  155. },
  156. {
  157. name: 'builder-data',
  158. mountPath: builderPath,
  159. },
  160. ],
  161. },
  162. ],
  163. volumes: [
  164. {
  165. name: 'subkey-data',
  166. emptyDir: {},
  167. },
  168. {
  169. name: 'builder-data',
  170. emptyDir: {},
  171. },
  172. {
  173. name: 'json-modify-script',
  174. configMap: {
  175. name: jsonModifyConfig,
  176. },
  177. },
  178. ],
  179. },
  180. },
  181. },
  182. },
  183. { ...resourceOptions }
  184. )
  185. // Export the Deployment name
  186. export const deploymentName = deployment.metadata.name
  187. // Create a LoadBalancer Service for the NGINX Deployment
  188. const service = new k8s.core.v1.Service(
  189. name,
  190. {
  191. metadata: {
  192. labels: appLabels,
  193. namespace: namespaceName,
  194. name: 'node-network',
  195. },
  196. spec: {
  197. ports: [
  198. { name: 'port-1', port: 9944, targetPort: 'rpc-9944' },
  199. { name: 'port-2', port: 9933, targetPort: 'rpc-9933' },
  200. { name: 'port-3', port: 30333, targetPort: 'rpc-30333' },
  201. ],
  202. selector: appLabels,
  203. },
  204. },
  205. resourceOptions
  206. )
  207. // Export the Service name and public LoadBalancer Endpoint
  208. export const serviceName = service.metadata.name
  209. const lbReady = config.get('isLoadBalancerReady') === 'true'
  210. const caddy = new CaddyServiceDeployment(
  211. 'caddy-proxy',
  212. { lbReady, namespaceName: namespaceName, isMinikube },
  213. resourceOptions
  214. )
  215. export const endpoint1 = caddy.primaryEndpoint
  216. export const endpoint2 = caddy.secondaryEndpoint