|
| 1 | += Deploying Custom Classes With the User Code Namespace |
| 2 | +:page-layout: tutorial |
| 3 | +:page-product: operator |
| 4 | +:page-categories: Cloud Native |
| 5 | +:page-lang: java |
| 6 | +:page-enterprise: true |
| 7 | +:page-est-time: 15 mins |
| 8 | +:github-directory: https://github.com/hazelcast-guides/hazelcast-platform-operator-user-code-namespace |
| 9 | +:description: Learn how to deploy custom classes with the User Code Namespace |
| 10 | + |
| 11 | +{description} |
| 12 | + |
| 13 | +== Context |
| 14 | + |
| 15 | +In this tutorial, you'll do the following: |
| 16 | + |
| 17 | +- Deploy Hazelcast with userCodeNamespaces enabled. |
| 18 | + |
| 19 | +- Create a custom EntryListener class and package it into a JAR. |
| 20 | + |
| 21 | +- Upload the JAR file to cloud storage. |
| 22 | + |
| 23 | +- Apply a UserCodeNamespace resource, referencing the JAR in storage. |
| 24 | + |
| 25 | +- Create a Map resource with the EntryListener, setting userCodeNamespaces the same as the UserCodeNamespace object. |
| 26 | + |
| 27 | +== Before you Begin |
| 28 | + |
| 29 | +You need the following: |
| 30 | + |
| 31 | +* Running https://kubernetes.io/[Kubernetes] cluster |
| 32 | +* Kubernetes command-line tool, https://kubernetes.io/docs/tasks/tools/#kubectl[kubectl] |
| 33 | +* Maven command-line tool, https://maven.apache.org/download.cgi[mvn] |
| 34 | +* Deployed xref:operator:ROOT:index.adoc[Hazelcast Platform Operator version 5.12 or above] |
| 35 | +* Blob storage and access credentials on one of the following cloud providers: https://aws.amazon.com/s3/[AWS], https://cloud.google.com/storage/[GCP], https://azure.microsoft.com/en-us/services/storage/blobs/[Azure] |
| 36 | + |
| 37 | +== Step 1. Start the Hazelcast Cluster |
| 38 | + |
| 39 | +. Create a license secret |
| 40 | ++ |
| 41 | +Create a secret with your link:http://trialrequest.hazelcast.com/[Hazelcast Enterprise License]. |
| 42 | ++ |
| 43 | +[source, shell] |
| 44 | +---- |
| 45 | +kubectl create secret generic hazelcast-license-key --from-literal=license-key=<hz-license-key> |
| 46 | +---- |
| 47 | + |
| 48 | +. Create the Hazelcast Cluster |
| 49 | ++ |
| 50 | +Run the following command to create the Hazelcast cluster with Persistence enabled using External type. |
| 51 | ++ |
| 52 | +[source, shell] |
| 53 | +---- |
| 54 | +kubectl apply -f - <<EOF |
| 55 | +include::ROOT:example$/operator-user-code-namespace/hazelcast.yaml[] |
| 56 | +EOF |
| 57 | +---- |
| 58 | + |
| 59 | +. Check the Cluster Status |
| 60 | ++ |
| 61 | +Run the following commands to see the cluster status |
| 62 | ++ |
| 63 | +[source, shell] |
| 64 | +---- |
| 65 | +$ kubectl get hazelcast hazelcast |
| 66 | +NAME STATUS MEMBERS |
| 67 | +hazelcast Running 1/1 |
| 68 | +---- |
| 69 | ++ |
| 70 | + |
| 71 | +== Step 2. Deploy the EntryListener JAR to Cloud Storage |
| 72 | + |
| 73 | +In this step, you’ll build the EntryListener JAR from the tutorial’s GitHub repository, and upload it to your cloud provider. |
| 74 | + |
| 75 | +. Clone the sample project. |
| 76 | + |
| 77 | ++ |
| 78 | +[tabs] |
| 79 | +==== |
| 80 | +HTTPS:: |
| 81 | ++ |
| 82 | +-- |
| 83 | +```bash |
| 84 | +git clone https://github.com/hazelcast-guides/hazelcast-platform-operator-user-code-namespace.git |
| 85 | +
|
| 86 | +cd hazelcast-platform-operator-user-code-namespace |
| 87 | +``` |
| 88 | +-- |
| 89 | +SSH:: |
| 90 | ++ |
| 91 | +-- |
| 92 | +```bash |
| 93 | +git clone git@github.com:hazelcast-guides/hazelcast-platform-operator-user-code-namespace.git |
| 94 | +
|
| 95 | +cd hazelcast-platform-operator-user-code-namespace |
| 96 | +``` |
| 97 | +-- |
| 98 | +==== |
| 99 | + |
| 100 | ++ |
| 101 | +The sample code for this tutorial is in the link:{github-directory}/tree/master/simple-entry-listener/src/main/java/com/hazelcast/tutorial[`simple-entry-listener/src/main/java/com/hazelcast/tutorial/`] directory: |
| 102 | + |
| 103 | +. Build the SimpleEntryListener JAR. |
| 104 | + |
| 105 | ++ |
| 106 | +[source, shell] |
| 107 | +---- |
| 108 | +mvn package -f ./simple-entry-listener |
| 109 | +---- |
| 110 | + |
| 111 | +. Upload the SimpleEntryListener JAR to the storage blob/bucket of your cloud provider, replacing the placeholder values. |
| 112 | + |
| 113 | ++ |
| 114 | +[tabs] |
| 115 | +==== |
| 116 | +
|
| 117 | +S3:: |
| 118 | ++ |
| 119 | +-- |
| 120 | +[source,bash] |
| 121 | +---- |
| 122 | +aws s3 cp simple-entry-listener/target/simple-entry-listener-1.0-SNAPSHOT.jar s3://<BUCKET_NAME> |
| 123 | +---- |
| 124 | +-- |
| 125 | +
|
| 126 | +GCS:: |
| 127 | ++ |
| 128 | +-- |
| 129 | +[source,bash] |
| 130 | +---- |
| 131 | +gsutil cp simple-entry-listener/target/simple-entry-listener-1.0-SNAPSHOT.jar gs://<BUCKET_NAME> |
| 132 | +---- |
| 133 | +-- |
| 134 | +
|
| 135 | +ABS:: |
| 136 | ++ |
| 137 | +-- |
| 138 | +[source,bash] |
| 139 | +---- |
| 140 | +az storage blob upload --account-name <ACCOUNT_NAME> --container-name <CONTAINER_NAME> --file simple-entry-listener/target/simple-entry-listener-1.0-SNAPSHOT.jar |
| 141 | +---- |
| 142 | +-- |
| 143 | +
|
| 144 | +==== |
| 145 | + |
| 146 | +. Create a secret for your cloud storage by running one of the following commands. Remember to replace the placeholder values. |
| 147 | + |
| 148 | ++ |
| 149 | +[tabs] |
| 150 | +==== |
| 151 | +
|
| 152 | +AWS:: |
| 153 | ++ |
| 154 | +-- |
| 155 | +[source,bash] |
| 156 | +---- |
| 157 | +kubectl create secret generic <SECRET-NAME> --from-literal=region=<region> \ |
| 158 | + --from-literal=access-key-id=<access-key-id> \ |
| 159 | + --from-literal=secret-access-key=<secret-access-key> |
| 160 | +---- |
| 161 | +-- |
| 162 | +
|
| 163 | +GCP:: |
| 164 | ++ |
| 165 | +-- |
| 166 | +[source,bash] |
| 167 | +---- |
| 168 | +kubectl create secret generic <SECRET-NAME> --from-file=google-credentials-path=<service_account_json_file> |
| 169 | +---- |
| 170 | +-- |
| 171 | +
|
| 172 | +Azure:: |
| 173 | ++ |
| 174 | +-- |
| 175 | +[source,bash] |
| 176 | +---- |
| 177 | +kubectl create secret generic <SECRET-NAME> \ |
| 178 | + --from-literal=storage-account=<storage-account> \ |
| 179 | + --from-literal=storage-key=<storage-key> |
| 180 | +---- |
| 181 | +-- |
| 182 | +
|
| 183 | +==== |
| 184 | + |
| 185 | +== Step 3. Apply the UserCodeNamespace resource |
| 186 | + |
| 187 | +. Apply the UserCodeNamespace resource |
| 188 | ++ |
| 189 | +Run the following command to create the UserCodeDeployment, referencing to the bucket where the EntryLister JAR is located. |
| 190 | ++ |
| 191 | +[source, shell] |
| 192 | +---- |
| 193 | +kubectl apply -f - <<EOF |
| 194 | +include::ROOT:example$/operator-user-code-namespace/ucn.yaml[] |
| 195 | +EOF |
| 196 | +---- |
| 197 | + |
| 198 | +. Check the status of the UserCodeNamespace resource |
| 199 | ++ |
| 200 | +Run the following command to check the status of the UserCodeDeployment resource |
| 201 | ++ |
| 202 | +[source, shell] |
| 203 | +---- |
| 204 | +$ kubectl get ucn my-ucn |
| 205 | +NAME STATUS |
| 206 | +my-ucn Success |
| 207 | +---- |
| 208 | + |
| 209 | ++ |
| 210 | +It verifies that: |
| 211 | + |
| 212 | +- The user code namespaces called `my-ucn` is created. |
| 213 | + |
| 214 | +- The jars in the bucket are downloaded into the members’ classpath. |
| 215 | + |
| 216 | +- The classes in the jars are added to the `my-ucn` namespace. |
| 217 | + |
| 218 | +== Step 4. Create the Map with the EntryListener |
| 219 | + |
| 220 | +. Create the Map in a specific namespace |
| 221 | ++ |
| 222 | +Run the following command to create the Map with the SimpleEntryListener class in the `my-ucn` namespace. |
| 223 | ++ |
| 224 | +[source, shell] |
| 225 | +---- |
| 226 | +kubectl apply -f - <<EOF |
| 227 | +include::ROOT:example$/operator-user-code-namespace/map.yaml[] |
| 228 | +EOF |
| 229 | +---- |
| 230 | + |
| 231 | +. Check the status of the Map |
| 232 | ++ |
| 233 | +Run the following command to check the status of the Map |
| 234 | ++ |
| 235 | +[source, shell] |
| 236 | +---- |
| 237 | +$ kubectl get map my-map |
| 238 | +NAME STATUS |
| 239 | +my-map Success |
| 240 | +---- |
| 241 | + |
| 242 | ++ |
| 243 | +The status of `my-map` is `Success`, indicating that the map was successfully created with the user code namespace `my-ucn` and includes one EntryListener class, `com.hazelcast.tutorial.SimpleEntryListener`. |
| 244 | ++ |
| 245 | +You can optionally put some entries to the map to observe the EntryListener in action. |
| 246 | ++ |
| 247 | +[source, shell] |
| 248 | +---- |
| 249 | +$ kubectl logs hazelcast-0 |
| 250 | +Entry Added:EntryEvent{entryEventType=ADDED, member=Member [10.80.2.23]:5702 - 237432e4-7a74-49ec-a2e5-d13ac9a8a41c this, name='my-map', key=gSMjgutLELKzZEEn, oldValue=null, value=LXqfGSOlYSIhMbTETLCNXgrYGbmdxCEpwmbPzmRkJjUCWUCu, mergingValue=null} |
| 251 | +Entry Added:EntryEvent{entryEventType=ADDED, member=Member [10.80.2.23]:5702 - 237432e4-7a74-49ec-a2e5-d13ac9a8a41c this, name='my-map', key=MehMxfDQQAzSlJHc, oldValue=null, value=GJTqmcmeSGPbRzQHjcSQDrQtttDxqwrFuginlqZRtxkUMCll, mergingValue=null} |
| 252 | +Entry Added:EntryEvent{entryEventType=ADDED, member=Member [10.80.2.23]:5702 - 237432e4-7a74-49ec-a2e5-d13ac9a8a41c this, name='my-map', key=YcSjQHklapAKVgZh, oldValue=null, value=QUmnTsqnTzivhROWpHlDujCuMwVnLzYSELwoNgWHkPEzwouL, mergingValue=null} |
| 253 | +Entry Added:EntryEvent{entryEventType=ADDED, member=Member [10.80.2.23]:5702 - 237432e4-7a74-49ec-a2e5-d13ac9a8a41c this, name='my-map', key=XeHNRdcizbNZQgZH, oldValue=null, value=SFuZPrNNDbhHCGwAHLQWZZVmTBLvCFcUAawGSKzyAetQOpEi, mergingValue=null} |
| 254 | +Entry Added:EntryEvent{entryEventType=ADDED, member=Member [10.80.2.23]:5702 - 237432e4-7a74-49ec-a2e5-d13ac9a8a41c this, name='my-map', key=mcPOBkUEmzBEkgXJ, oldValue=null, value=oTKCqSFoExFHuRKtzUcLjFdPbSPLihVBPfvafiQXppayJzom, mergingValue=null} |
| 255 | +---- |
| 256 | + |
| 257 | +== Step 6. Clean Up |
| 258 | + |
| 259 | +To clean up the created resources remove the secrets and Hazelcast Custom Resources. |
| 260 | + |
| 261 | +[source, shell] |
| 262 | +---- |
| 263 | +$ kubectl delete secret <external-bucket-secret-name> |
| 264 | +$ kubectl delete secret hazelcast-license-key |
| 265 | +$ kubectl delete hazelcast hazelcast |
| 266 | +---- |
| 267 | + |
| 268 | +== See Also |
| 269 | + |
| 270 | +- xref:operator:ROOT:user-code-namespaces.adoc[] |
0 commit comments