Custom Container Delivery

If the default webservice component type is not suitable for your team, and you want to get a more simple way to deploy your business application. This guide will help you. Before, you must have the platform manager’s permission.

Simplify the webservice type

The default webservice component type has more than 10 properties. Maybe your developer only needs to configure the image path and resource limits. For the other properties, the team could set the default values. If so, you could change the webservice definition.

  1. Change the UI schema to hide some fields

This way is only suitable the UI users.

image

On the definition detail page, users could customize the UI schema to setting the UI forms. For example, if you want to hide the ExposeType field, only need to set the disable is true.

  1. ...
  2. - jsonKey: exposeType
  3. uiType: Select
  4. label: ExposeType
  5. disable: true
  6. ...

More references: UI Schema

  1. Change the definition and remove or add some fields

If you want to completely remove or add some fields, you should edit the component definition.

This guide should learn the CUE language.

  1. vela def get webservice > custom-webservice.cue

Refer to the CUE Basic and Component Definition documents to learn how to custom the custom-webservice.cue.

After edit:

  1. vela def apply custom-webservice.cue

Create a new component type to deploy the war package

If your team uses the war package to deploy the Java application. In KubeVela you could create a new component type to deploy the War package.

  1. "java-war": {
  2. alias: ""
  3. annotations: {}
  4. attributes: {
  5. workload: {
  6. definition: {
  7. apiVersion: "apps/v1"
  8. kind: "Deployment"
  9. }
  10. type: "deployments.apps"
  11. }
  12. status: {
  13. customStatus: #"""
  14. ready: {
  15. readyReplicas: *0 | int
  16. } & {
  17. if context.output.status.readyReplicas != _|_ {
  18. readyReplicas: context.output.status.readyReplicas
  19. }
  20. }
  21. message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
  22. """#
  23. healthPolicy: #"""
  24. ready: {
  25. updatedReplicas: *0 | int
  26. readyReplicas: *0 | int
  27. replicas: *0 | int
  28. observedGeneration: *0 | int
  29. } & {
  30. if context.output.status.updatedReplicas != _|_ {
  31. updatedReplicas: context.output.status.updatedReplicas
  32. }
  33. if context.output.status.readyReplicas != _|_ {
  34. readyReplicas: context.output.status.readyReplicas
  35. }
  36. if context.output.status.replicas != _|_ {
  37. replicas: context.output.status.replicas
  38. }
  39. if context.output.status.observedGeneration != _|_ {
  40. observedGeneration: context.output.status.observedGeneration
  41. }
  42. }
  43. isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
  44. """#
  45. }
  46. }
  47. description: ""
  48. labels: {}
  49. type: "component"
  50. }
  51. template: {
  52. output: {
  53. apiVersion: "apps/v1"
  54. kind: "Deployment"
  55. metadata: {
  56. name: context.name
  57. namespace: context.namespace
  58. }
  59. spec: {
  60. replicas: parameter.replicas
  61. selector: {
  62. matchLabels: {
  63. "app.oam.dev/component": context.name
  64. }
  65. }
  66. template: {
  67. metadata: {
  68. labels: {
  69. "app.oam.dev/name": context.appName
  70. "app.oam.dev/component": context.name
  71. "app.oam.dev/revision": context.revision
  72. }
  73. }
  74. spec: {
  75. initContainers: [{
  76. name: "prepare-war"
  77. image: "busybox"
  78. if parameter["deployToRoot"] != _|_ {
  79. if parameter["deployToRoot"] {
  80. command: ["wget", "-O", "/usr/local/tomcat/webapps/ROOT.war", parameter["warURL"]]
  81. }
  82. }
  83. if parameter["deployToRoot"] == _|_ {
  84. command: ["wget", "-P", "/usr/local/tomcat/webapps/", parameter["warURL"]]
  85. }
  86. volumeMounts: [{
  87. name: "webapps"
  88. mountPath: "/usr/local/tomcat/webapps"
  89. }]
  90. }]
  91. containers: [{
  92. name: context.name
  93. image: "tomcat:" + parameter["envVersion"]
  94. if parameter["cpu"] != _|_ {
  95. resources: {
  96. limits: cpu: parameter.cpu
  97. requests: cpu: parameter.cpu
  98. }
  99. }
  100. if parameter["memory"] != _|_ {
  101. resources: {
  102. limits: memory: parameter.memory
  103. requests: memory: parameter.memory
  104. }
  105. }
  106. ports: [{
  107. containerPort: 8080
  108. name: "webapp"
  109. }]
  110. _envs: {
  111. custom: *parameter["env"] | []
  112. inner: [
  113. if parameter["javaOpts"] != _|_ {
  114. {
  115. name: "JAVA_OPTS"
  116. value: parameter.javaOpts
  117. }
  118. },
  119. ]
  120. }
  121. env: _envs.custom + _envs.inner
  122. volumeMounts: [{
  123. name: "webapps"
  124. mountPath: "/usr/local/tomcat/webapps"
  125. }]
  126. }]
  127. volumes: [{
  128. name: "webapps"
  129. emptyDir: {}
  130. }]
  131. }
  132. }
  133. }
  134. }
  135. outputs: {
  136. services: {
  137. kind: "Service"
  138. apiVersion: "v1"
  139. metadata: {
  140. name: context.name
  141. namespace: context.namespace
  142. }
  143. spec: {
  144. selector: "app.oam.dev/component": context.name
  145. ports: [{
  146. port: 8080
  147. }]
  148. type: "ClusterIP"
  149. }
  150. }
  151. }
  152. parameter: {
  153. // +usage=The URL of the war package.
  154. warURL: string
  155. // +usage=Select a environment version([tomcat version]-[jdk version])
  156. envVersion: *"8-jdk8" | "9-jdk8" | "10-jdk8" | "8-jdk11" | "9-jdk11" | "10-jdk11" | "8-jdk17" | "9-jdk17" | "10-jdk17"
  157. // +usage=Specifies the number of replicas.
  158. replicas: *1 | int
  159. // +usage=Define arguments by using environment variables
  160. env?: [...{
  161. name: string
  162. value?: string
  163. }]
  164. // +usage=Setting the Java Opts configuration.
  165. javaOpts?: string
  166. // +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)
  167. cpu?: string
  168. // +usage=Specifies the attributes of the memory resource required for the container.
  169. memory?: =~"^([1-9][0-9]{0,63})(E|P|T|G|M|K|Ei|Pi|Ti|Gi|Mi|Ki)$"
  170. deployToRoot?: bool
  171. }
  172. }

Copy the definition and create a file java-war.cue, then:

  1. vela def apply java-war.cue

Now, other developers could create the application with a war URL, for example:

  1. apiVersion: core.oam.dev/v1beta1
  2. kind: Application
  3. metadata:
  4. name: nanoservice
  5. namespace: e2e-test
  6. spec:
  7. components:
  8. - name: catalog
  9. properties:
  10. envVersion: 8-jdk8
  11. replicas: 1
  12. warURL: https://static.kubevela.net/example/java-example/nanoservice/catalog.war
  13. type: java-war
  14. - name: customer
  15. properties:
  16. envVersion: 8-jdk8
  17. replicas: 1
  18. warURL: https://static.kubevela.net/example/java-example/nanoservice/customer.war
  19. type: java-war
  20. - dependsOn:
  21. - catalog
  22. - customer
  23. name: order
  24. properties:
  25. env:
  26. - name: CATALOG_HOST
  27. value: catalog
  28. - name: CUSTOMER_HOST
  29. value: customer
  30. envVersion: 8-jdk8
  31. javaOpts: -Xms512m -Xmx512m -Xss256K
  32. replicas: 1
  33. warURL: https://static.kubevela.net/example/java-example/nanoservice/order.war
  34. traits:
  35. - properties:
  36. domains:
  37. - nanoservice.beijing.kubevela.net
  38. rules:
  39. - path:
  40. type: PathPrefix
  41. value: /order
  42. port: 8080
  43. type: http-route
  44. type: java-war
  45. policies:
  46. - name: e2e-test
  47. properties:
  48. clusters:
  49. - local
  50. namespace: e2e-test
  51. type: topology
  52. workflow:
  53. steps:
  54. - name: deploy2-e2e-test
  55. properties:
  56. policies:
  57. - e2e-test
  58. type: deploy

java-app

This example includes three components, and the order service depends on the catalog and the customer services. The developer only needs to care about the war package URL and the tomcat/JRE version, they are familiar to the Java developer. The developer should upload the war package to a repository, such as Jfrog. Get a download URL to assign to the warURL field.

In the same way, you could create a component type to deploy the Jar package and other’s binary packages.