index.ts 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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. const config = new pulumi.Config()
  7. const awsConfig = new pulumi.Config('aws')
  8. const isMinikube = config.getBoolean('isMinikube')
  9. export let kubeconfig: pulumi.Output<any>
  10. export let joystreamAppsImage: pulumi.Output<string>
  11. let provider: k8s.Provider
  12. if (isMinikube) {
  13. provider = new k8s.Provider('local', {})
  14. // Create image from local app
  15. // joystreamAppsImage = new docker.Image('joystream/apps', {
  16. // build: {
  17. // context: '../../../',
  18. // dockerfile: '../../../apps.Dockerfile',
  19. // },
  20. // imageName: 'joystream/apps:latest',
  21. // skipPush: true,
  22. // }).baseImageName
  23. // joystreamAppsImage = pulumi.interpolate`joystream/apps`
  24. } else {
  25. // Create a VPC for our cluster.
  26. const vpc = new awsx.ec2.Vpc('joystream-node-vpc', { numberOfAvailabilityZones: 2 })
  27. // Create an EKS cluster with the default configuration.
  28. const cluster = new eks.Cluster('eksctl-my-cluster', {
  29. vpcId: vpc.id,
  30. subnetIds: vpc.publicSubnetIds,
  31. desiredCapacity: 3,
  32. maxSize: 3,
  33. instanceType: 't2.large',
  34. providerCredentialOpts: {
  35. profileName: awsConfig.get('profile'),
  36. },
  37. })
  38. provider = cluster.provider
  39. // Export the cluster's kubeconfig.
  40. kubeconfig = cluster.kubeconfig
  41. }
  42. const resourceOptions = { provider: provider }
  43. const name = 'node-network'
  44. // Create a Kubernetes Namespace
  45. // const ns = new k8s.core.v1.Namespace(name, {}, { provider: cluster.provider })
  46. const ns = new k8s.core.v1.Namespace(name, {}, resourceOptions)
  47. // Export the Namespace name
  48. export const namespaceName = ns.metadata.name
  49. const appLabels = { appClass: name }
  50. const jsonModifyConfig = new configMapFromFile(
  51. 'json-modify-config',
  52. {
  53. filePath: 'json_modify.py',
  54. namespaceName: namespaceName,
  55. },
  56. resourceOptions
  57. ).configName
  58. const dataPath = '/subkey-data'
  59. const builderPath = '/builder-data'
  60. const networkPrefix = '8129'
  61. const chainSpecPath = `${builderPath}/chainspec-raw.json`
  62. const deployment = new k8s.apps.v1.Deployment(
  63. name,
  64. {
  65. metadata: {
  66. namespace: namespaceName,
  67. labels: appLabels,
  68. },
  69. spec: {
  70. replicas: 1,
  71. selector: { matchLabels: appLabels },
  72. template: {
  73. metadata: {
  74. labels: appLabels,
  75. },
  76. spec: {
  77. initContainers: [
  78. {
  79. name: 'subkey-node',
  80. image: 'parity/subkey:latest',
  81. command: ['/bin/sh', '-c'],
  82. args: [`subkey generate-node-key >> ${dataPath}/privatekey1 2>> ${dataPath}/publickey1`],
  83. volumeMounts: [
  84. {
  85. name: 'subkey-data',
  86. mountPath: dataPath,
  87. },
  88. ],
  89. },
  90. {
  91. name: 'subkey-node-1',
  92. image: 'parity/subkey:latest',
  93. command: ['/bin/sh', '-c'],
  94. args: [`subkey generate-node-key >> ${dataPath}/privatekey2 2>> ${dataPath}/publickey2`],
  95. volumeMounts: [
  96. {
  97. name: 'subkey-data',
  98. mountPath: dataPath,
  99. },
  100. ],
  101. },
  102. {
  103. name: 'builder-node',
  104. image: 'joystream/node:latest',
  105. command: ['/bin/sh', '-c'],
  106. args: [
  107. `/joystream/chain-spec-builder generate -a 2 --chain-spec-path ${builderPath}/chainspec.json --deployment live --endowed 1 --keystore-path ${builderPath}/data >> ${builderPath}/seeds.txt`,
  108. ],
  109. volumeMounts: [
  110. {
  111. name: 'builder-data',
  112. mountPath: builderPath,
  113. },
  114. ],
  115. },
  116. {
  117. name: 'json-modify',
  118. image: 'python',
  119. command: ['python'],
  120. args: ['/scripts/json_modify.py', '--path', `${builderPath}/chainspec.json`, '--prefix', networkPrefix],
  121. volumeMounts: [
  122. {
  123. mountPath: '/scripts/json_modify.py',
  124. name: 'json-modify-script',
  125. subPath: 'fileData',
  126. },
  127. {
  128. name: 'builder-data',
  129. mountPath: builderPath,
  130. },
  131. {
  132. name: 'subkey-data',
  133. mountPath: dataPath,
  134. },
  135. ],
  136. },
  137. {
  138. name: 'raw-chain-spec',
  139. image: 'joystream/node:latest',
  140. command: ['/bin/sh', '-c'],
  141. args: [`/joystream/node build-spec --chain ${builderPath}/chainspec.json --raw > ${chainSpecPath}`],
  142. volumeMounts: [
  143. {
  144. name: 'builder-data',
  145. mountPath: builderPath,
  146. },
  147. ],
  148. },
  149. ],
  150. containers: [
  151. {
  152. name: 'joystream-node',
  153. image: 'joystream/node:latest',
  154. ports: [{ containerPort: 9944 }, { containerPort: 9933 }],
  155. args: [
  156. '--chain',
  157. chainSpecPath,
  158. '--pruning',
  159. 'archive',
  160. '--node-key-file',
  161. `${dataPath}/privatekey1`,
  162. '--keystore-path',
  163. `${builderPath}/data/auth-0`,
  164. '--validator',
  165. '--log',
  166. 'runtime,txpool,transaction-pool,trace=sync',
  167. ],
  168. volumeMounts: [
  169. {
  170. name: 'subkey-data',
  171. mountPath: dataPath,
  172. },
  173. {
  174. name: 'builder-data',
  175. mountPath: builderPath,
  176. },
  177. ],
  178. },
  179. {
  180. name: 'joystream-node-2',
  181. image: 'joystream/node:latest',
  182. ports: [{ containerPort: 9944 }, { containerPort: 9933 }],
  183. args: [
  184. '--chain',
  185. chainSpecPath,
  186. '--pruning',
  187. 'archive',
  188. '--node-key-file',
  189. `${dataPath}/privatekey2`,
  190. '--keystore-path',
  191. `${builderPath}/data/auth-1`,
  192. '--validator',
  193. '--log',
  194. 'runtime,txpool,transaction-pool,trace=sync',
  195. ],
  196. volumeMounts: [
  197. {
  198. name: 'subkey-data',
  199. mountPath: dataPath,
  200. },
  201. {
  202. name: 'builder-data',
  203. mountPath: builderPath,
  204. },
  205. ],
  206. },
  207. {
  208. name: 'rpc-node',
  209. image: 'joystream/node:latest',
  210. ports: [{ containerPort: 9944 }, { containerPort: 9933 }, { containerPort: 30333 }],
  211. args: [
  212. '--chain',
  213. chainSpecPath,
  214. '--ws-external',
  215. '--rpc-cors',
  216. 'all',
  217. '--pruning',
  218. 'archive',
  219. '--ws-max-connections',
  220. '512',
  221. '--telemetry-url',
  222. 'wss://telemetry.joystream.org/submit/ 0',
  223. '--telemetry-url',
  224. 'wss://telemetry.polkadot.io/submit/ 0',
  225. ],
  226. volumeMounts: [
  227. {
  228. name: 'subkey-data',
  229. mountPath: dataPath,
  230. },
  231. {
  232. name: 'builder-data',
  233. mountPath: builderPath,
  234. },
  235. ],
  236. },
  237. ],
  238. volumes: [
  239. {
  240. name: 'subkey-data',
  241. emptyDir: {},
  242. },
  243. {
  244. name: 'builder-data',
  245. emptyDir: {},
  246. },
  247. {
  248. name: 'json-modify-script',
  249. configMap: {
  250. name: jsonModifyConfig,
  251. },
  252. },
  253. ],
  254. },
  255. },
  256. },
  257. },
  258. { ...resourceOptions }
  259. )
  260. // Export the Deployment name
  261. export const deploymentName = deployment.metadata.name
  262. // Create a LoadBalancer Service for the NGINX Deployment
  263. const service = new k8s.core.v1.Service(
  264. name,
  265. {
  266. metadata: {
  267. labels: appLabels,
  268. namespace: namespaceName,
  269. },
  270. spec: {
  271. type: 'NodePort',
  272. ports: [
  273. { name: 'port-1', port: 9944 },
  274. { name: 'port-2', port: 9933 },
  275. ],
  276. selector: appLabels,
  277. },
  278. },
  279. resourceOptions
  280. )
  281. // Export the Service name and public LoadBalancer Endpoint
  282. export const serviceName = service.metadata.name
  283. // When "done", this will print the public IP.
  284. export let serviceHostname: pulumi.Output<string>
  285. if (isMinikube) {
  286. serviceHostname = service.spec.clusterIP
  287. } else {
  288. serviceHostname = service.status.loadBalancer.ingress[0].hostname
  289. }