Skip to content

Commit f484af7

Browse files
committed
Merge remote-tracking branch 'origin/main' into move-scalingAction
2 parents 4411e31 + 78eb03a commit f484af7

File tree

9 files changed

+147
-309
lines changed

9 files changed

+147
-309
lines changed

documentation/site/content/managing-domains/domain-lifecycle/scaling.md

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ The operator provides several ways to initiate scaling of WebLogic clusters, inc
2323
* [Using Domain lifecycle sample scripts](#using-domain-lifecycle-sample-scripts)
2424
* [Calling the operator's REST scale API, for example, from `curl`](#calling-the-operators-rest-scale-api)
2525
* [Kubernetes Horizontal Pod Autoscaler (HPA)](#kubernetes-horizontal-pod-autoscaler-hpa)
26-
* [Using a WLDF policy rule and script action to call the operator's REST scale API](#using-a-wldf-policy-rule-and-script-action-to-call-the-operators-rest-scale-api)
27-
* [Using a Prometheus alert action to call the operator's REST scale API](#using-a-prometheus-alert-action-to-call-the-operators-rest-scale-api)
26+
* [Using a WLDF policy rule and script action to call the scaling script](#using-a-wldf-policy-rule-and-script-action-to-call-the-scaling-script)
27+
* [Using a Prometheus alert action to call the scaling script](#using-a-prometheus-alert-action-to-call-the-scaling-script)
2828

2929
### `kubectl` CLI commands
3030
Use the Kubernetes command-line tool, `kubectl`, to manually scale WebLogic clusters with the following commands:
@@ -221,19 +221,15 @@ $ kubectl exec --stdin --tty sample-domain1-managed-server1 -- /bin/bash
221221

222222
For more in-depth information on the Kubernetes Horizontal Pod Autoscaler, see [Horizontal Pod Autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/).
223223

224-
#### Using a WLDF policy rule and script action to call the operator's REST scale API
224+
#### Using a WLDF policy rule and script action to call the scaling script
225225
The WebLogic Diagnostics Framework (WLDF) is a suite of services and APIs that collect and surface metrics that provide visibility into server and application performance.
226226
To support automatic scaling of WebLogic clusters in Kubernetes, WLDF provides the Policies and Actions component, which lets you write policy expressions for automatically executing scaling
227227
operations on a cluster. These policies monitor one or more types of WebLogic Server metrics, such as memory, idle threads, and CPU load. When the configured threshold
228228
in a policy is met, the policy is triggered, and the corresponding scaling action is executed. The WebLogic Kubernetes Operator project provides a shell script, [`scalingAction.sh`](https://github.com/oracle/weblogic-kubernetes-operator/blob/{{< latestMinorVersion >}}/kubernetes/samples/scripts/scaling/scalingAction.sh),
229-
for use as a Script Action, which illustrates how to issue a request to the operator’s REST endpoint.
230-
231-
{{% notice note %}}
232-
Beginning with operator version 4.0.5, the operator's REST endpoint is disabled by default. Install the operator with the Helm install option `--set "enableRest=true"` to enable the REST endpoint.
233-
{{% /notice %}}
229+
for use as a Script Action, which initiates a scaling of the selected cluster.
234230

235231
##### Configure automatic scaling of WebLogic clusters in Kubernetes with WLDF
236-
The following steps are provided as a guideline on how to configure a WLDF Policy and Script Action component for issuing scaling requests to the operator's REST endpoint:
232+
The following steps are provided as a guideline on how to configure a WLDF Policy and Script Action component for issuing scaling requests:
237233

238234
1. Copy the [`scalingAction.sh`](https://github.com/oracle/weblogic-kubernetes-operator/blob/{{< latestMinorVersion >}}/kubernetes/samples/scripts/scaling/scalingAction.sh) script to `$DOMAIN_HOME/bin/scripts` so that it's accessible within the Administration Server pod. For more information, see [Configuring Script Actions](https://docs.oracle.com/en/middleware/standalone/weblogic-server/14.1.1.0/wldfc/config_notifications.html#GUID-5CC52534-13CD-40D9-915D-3380C86580F1) in _Configuring and Using the Diagnostics Framework for Oracle WebLogic Server_.
239235

@@ -244,23 +240,6 @@ see [Configuring Policies and Actions](https://docs.oracle.com/en/middleware/sta
244240

245241
b. Configure a WLDF script action and associate the [`scalingAction.sh`](https://github.com/oracle/weblogic-kubernetes-operator/blob/{{< latestMinorVersion >}}/kubernetes/samples/scripts/scaling/scalingAction.sh) script.
246242

247-
Important notes about the configuration properties for the Script Action:
248-
249-
The `scalingAction.sh` script requires access to the SSL certificate of the operator’s endpoint and this is provided through the environment variable `INTERNAL_OPERATOR_CERT`.
250-
The operator’s SSL certificate can be found in the `internalOperatorCert` entry of the operator’s ConfigMap `weblogic-operator-cm`:
251-
252-
For example:
253-
```none
254-
#> kubectl describe configmap weblogic-operator-cm -n weblogic-operator
255-
...
256-
Data
257-
====
258-
internalOperatorCert:
259-
----
260-
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR3akNDQXFxZ0F3SUJBZ0lFRzhYT1N6QU...
261-
...
262-
```
263-
264243
The scalingAction.sh script accepts a number of customizable parameters:
265244

266245
* `action` - scaleUp or scaleDown (Required)
@@ -279,12 +258,6 @@ Set this to `https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}` when
279258

280259
* `wls_domain_namespace` - Kubernetes Namespace in which the WebLogic domain is defined, default=`default`
281260

282-
* `operator_service_name` - WebLogic Kubernetes Operator Service name of the REST endpoint, default=`internal-weblogic-operator-service`
283-
284-
* `operator_service_account` - Kubernetes Service Account name for the operator, default=`weblogic-operator`
285-
286-
* `operator_namespace` – Namespace in which the operator is deployed, default=`weblogic-operator`
287-
288261
* `scaling_size` – Incremental number of Managed Server instances by which to scale up or down, default=`1`
289262

290263
You can use any of the following tools to configure policies for diagnostic system modules:
@@ -294,7 +267,7 @@ You can use any of the following tools to configure policies for diagnostic syst
294267
* REST
295268
* JMX application
296269

297-
A more in-depth description and example on using WLDF's Policies and Actions component for initiating scaling requests through the operator's REST endpoint can be found in the blogs:
270+
A more in-depth description and example on using WLDF's Policies and Actions component for initiating scaling requests can be found in the blogs:
298271

299272
* [Automatic Scaling of WebLogic Clusters on Kubernetes](https://blogs.oracle.com/weblogicserver/automatic-scaling-of-weblogic-clusters-on-kubernetes-v2)
300273
* [WebLogic Dynamic Clusters on Kubernetes](https://blogs.oracle.com/weblogicserver/weblogic-dynamic-clusters-on-kubernetes)
@@ -313,11 +286,8 @@ apiVersion: rbac.authorization.k8s.io/v1
313286
metadata:
314287
name: weblogic-domain-cluster-role
315288
rules:
316-
- apiGroups: [""]
317-
resources: ["services/status"]
318-
verbs: ["get", "list", "watch"]
319289
- apiGroups: ["weblogic.oracle"]
320-
resources: ["domains"]
290+
resources: ["domains", "clusters", "clusters/scale"]
321291
verbs: ["get", "list", "patch", "update"]
322292
---
323293
#
@@ -360,7 +330,7 @@ roleRef:
360330
#### Horizontal Pod Autoscaler (HPA) using WebLogic Exporter Metrics
361331
Please read this blog post to learn how to scale a WebLogic cluster, based on WebLogic metrics provided by the Monitoring Exporter, using the Kubernetes Horizontal Pod Autoscaler (HPA). We will use the Prometheus Adapter to gather the names of the available metrics from Prometheus at regular intervals. A custom configuration of the adapter will expose only metrics that follow specific formats. [Horizontal Pod Autoscaler (HPA) using WebLogic Exporter Metrics](https://blogs.oracle.com/weblogicserver/post/horizontal-pod-autoscaler-hpausing-weblogic-exporter-metrics). See this corresponding video for a demonstration of the blog post in action. [WebLogic Kubernetes Operator support for Kubernetes Horizontal Pod Autoscaling](https://www.youtube.com/watch?v=aKBG6yJ3sMg).
362332

363-
#### Using a Prometheus alert action to call the operator's REST scale API
333+
#### Using a Prometheus alert action to call the scaling script
364334
In addition to using the WebLogic Diagnostic Framework for automatic scaling of a dynamic cluster,
365335
you can use a third-party monitoring application like Prometheus. Please read the following blog for
366336
details about [Using Prometheus to Automatically Scale WebLogic Clusters on Kubernetes](https://blogs.oracle.com/weblogicserver/using-prometheus-to-automatically-scale-weblogic-clusters-on-kubernetes-v5).

integration-tests/src/test/java/oracle/weblogic/kubernetes/ItReadOnlyRootFS.java

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -554,36 +554,16 @@ private static void validateContainerSpec(V1Container container, String podName,
554554
logger.info("PASS: Container " + containerName + " in pod " + podName + " has readOnlyRootFilesystem=true");
555555
}
556556

557-
if (!isInitContainer) {
558-
// 2. For regular containers, exec to check /tmp mount
559-
try {
560-
561-
ExecResult result = execCommand(namespace, podName, containerName, true, "df", "-h", "/tmp");
562-
String stdout = result.stdout();
563-
if (stdout == null || !stdout.contains("tmpfs")) {
564-
String msg = "FAIL: /tmp is not mounted as tmpfs in container " + containerName + " in pod " + podName;
565-
logger.severe(msg);
566-
failures.add(msg);
567-
} else {
568-
logger.info("PASS: /tmp is mounted as tmpfs in container " + containerName + " in pod " + podName);
569-
}
570-
} catch (Exception e) {
571-
String msg = "FAIL: Exec failed for container " + containerName + " in pod " + podName + ": " + e.getMessage();
572-
logger.severe(msg);
573-
failures.add(msg);
574-
}
557+
// 2. Check volumeMounts
558+
List<V1VolumeMount> volumeMounts = container.getVolumeMounts();
559+
boolean hasTmpMount = volumeMounts != null && volumeMounts.stream()
560+
.anyMatch(mount -> mount.getMountPath() != null && mount.getMountPath().startsWith("/tmp"));
561+
if (!hasTmpMount) {
562+
String msg = "FAIL: container " + containerName + " in pod " + podName + " does not have /tmp mounted";
563+
logger.severe(msg);
564+
failures.add(msg);
575565
} else {
576-
// 3. For init container, check volumeMounts
577-
List<V1VolumeMount> volumeMounts = container.getVolumeMounts();
578-
boolean hasTmpMount = volumeMounts != null && volumeMounts.stream()
579-
.anyMatch(mount -> mount.getMountPath() != null && mount.getMountPath().startsWith("/tmp"));
580-
if (!hasTmpMount) {
581-
String msg = "FAIL: Init container " + containerName + " in pod " + podName + " does not have /tmp mounted";
582-
logger.severe(msg);
583-
failures.add(msg);
584-
} else {
585-
logger.info("PASS: Init container " + containerName + " in pod " + podName + " has /tmp mounted");
586-
}
566+
logger.info("PASS: container " + containerName + " in pod " + podName + " has /tmp mounted");
587567
}
588568
}
589569

integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/Domain.java

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package oracle.weblogic.kubernetes.actions.impl;
55

66
import java.io.IOException;
7+
import java.nio.file.Files;
78
import java.nio.file.Path;
89
import java.nio.file.Paths;
910
import java.util.ArrayList;
@@ -1068,12 +1069,39 @@ private static boolean copyFileFromPod(String namespace,
10681069
return true;
10691070
}
10701071

1071-
private static void scaleViaScript(String opNamespace, String domainNamespace,
1072+
private static boolean scaleViaScript(String opNamespace, String domainNamespace,
10721073
String domainUid, String scalingAction, String clusterName,
10731074
String opServiceAccount, int scalingSize,
10741075
String domainHomeLocation,
10751076
V1Pod adminPod) {
10761077
LoggingFacade logger = getLogger();
1078+
1079+
String secretName = Secret.getSecretOfServiceAccount(opNamespace, opServiceAccount);
1080+
if (secretName.isEmpty()) {
1081+
logger.info("Did not find secret of service account {0} in namespace {1}", opServiceAccount, opNamespace);
1082+
return false;
1083+
}
1084+
logger.info("Got secret {0} of service account {1} in namespace {2}",
1085+
secretName, opServiceAccount, opNamespace);
1086+
1087+
logger.info("Getting service account token stored in secret {0} to authenticate as service account {1}"
1088+
+ " in namespace {2}", secretName, opServiceAccount, opNamespace);
1089+
String secretToken = Secret.getSecretEncodedToken(opNamespace, secretName);
1090+
if (secretToken == null || secretToken.isEmpty()) {
1091+
logger.info("Did not get encoded token for secret {0} associated with service account {1} in namespace {2}",
1092+
secretName, opServiceAccount, opNamespace);
1093+
return false;
1094+
}
1095+
logger.info("Got encoded token for secret {0} associated with service account {1} in namespace {2}: {3}",
1096+
secretName, opServiceAccount, opNamespace, secretToken);
1097+
1098+
// decode the secret encoded token
1099+
String decodedToken = OKD ? secretToken : new String(Base64.getDecoder().decode(secretToken));
1100+
logger.info("Got decoded token for secret {0} associated with service account {1} in namespace {2}: {3}",
1101+
secretName, opServiceAccount, opNamespace, decodedToken);
1102+
1103+
assertNotNull(decodedToken, "Couldn't get secret, token is null");
1104+
10771105
StringBuffer scalingCommand = new StringBuffer()
10781106
//.append(Paths.get(domainHomeLocation + "/bin/scripts/scalingAction.sh"))
10791107
.append(Paths.get("cd /u01; /u01/scalingAction.sh"))
@@ -1085,12 +1113,8 @@ private static void scaleViaScript(String opNamespace, String domainNamespace,
10851113
.append(domainNamespace)
10861114
.append(" --cluster_name=")
10871115
.append(clusterName)
1088-
.append(" --operator_namespace=")
1089-
.append(opNamespace)
1090-
.append(" --operator_service_account=")
1091-
.append(opServiceAccount)
1092-
.append(" --operator_service_name=")
1093-
.append("internal-weblogic-operator-svc")
1116+
.append(" --access_token=")
1117+
.append(decodedToken)
10941118
.append(" --scaling_size=")
10951119
.append(scalingSize)
10961120
.append(" --kubernetes_master=")
@@ -1103,6 +1127,8 @@ private static void scaleViaScript(String opNamespace, String domainNamespace,
11031127
ExecResult result = null;
11041128
assertNotNull(adminPod, "admin pod is null");
11051129
assertNotNull(adminPod.getMetadata(), "admin pod metadata is null");
1130+
Path scalingActionLogPath = Paths.get(RESULTS_ROOT + "/" + domainUid + "-scalingAction.log");
1131+
Path scalingActionOutPath = Paths.get(RESULTS_ROOT + "/" + domainUid + "-scalingAction.out");
11061132
try {
11071133
result = assertDoesNotThrow(() -> Kubernetes.exec(adminPod, null, true,
11081134
"/bin/sh", "-c", commandToExecuteInsidePod),
@@ -1119,42 +1145,58 @@ private static void scaleViaScript(String opNamespace, String domainNamespace,
11191145
testUntil(
11201146
() -> copyFileFromPod(domainNamespace, adminPod.getMetadata().getName(), null,
11211147
"/u01/scalingAction.log",
1122-
Paths.get(RESULTS_ROOT + "/" + domainUid + "-scalingAction.log")),
1148+
scalingActionLogPath),
11231149
logger,
11241150
"Copying scalingAction.log from admin server pod");
11251151
// copy scalingAction.out to local
11261152
testUntil(
11271153
() -> copyFileFromPod(domainNamespace, adminPod.getMetadata().getName(), null,
11281154
"/u01/scalingAction.out",
1129-
Paths.get(RESULTS_ROOT + "/" + domainUid + "-scalingAction.out")),
1155+
scalingActionOutPath),
11301156
logger,
11311157
"Copying scalingAction.out from admin server pod");
1158+
1159+
try {
1160+
logger.info("Contents of scalingAction.log:\n" + Files.readString(scalingActionLogPath));
1161+
logger.info("Contents of scalingAction.out:\n" + Files.readString(scalingActionOutPath));
1162+
} catch (IOException ioex) {
1163+
// no-op
1164+
}
1165+
11321166
throw err;
11331167

11341168
}
11351169
// copy scalingAction.log to local
11361170
testUntil(
11371171
() -> copyFileFromPod(domainNamespace, adminPod.getMetadata().getName(), null,
11381172
"/u01/scalingAction.log",
1139-
Paths.get(RESULTS_ROOT + "/" + domainUid + "-scalingAction.log")),
1173+
scalingActionLogPath),
11401174
logger,
11411175
"Copying scalingAction.log from admin server pod");
11421176
// copy scalingAction.out to local
11431177
testUntil(
11441178
() -> copyFileFromPod(domainNamespace, adminPod.getMetadata().getName(), null,
11451179
"/u01/scalingAction.out",
1146-
Paths.get(RESULTS_ROOT + "/" + domainUid + "-scalingAction.out")),
1180+
scalingActionOutPath),
11471181
logger,
11481182
"Copying scalingAction.out from admin server pod");
11491183
// domainHomeLocation + "/bin/scripts/scalingAction.log",
11501184

1185+
try {
1186+
logger.info("Contents of scalingAction.log:\n" + Files.readString(scalingActionLogPath));
1187+
logger.info("Contents of scalingAction.out:\n" + Files.readString(scalingActionOutPath));
1188+
} catch (IOException ioex) {
1189+
// no-op
1190+
}
1191+
11511192
// checking for exitValue 0 for success fails sometimes as k8s exec api returns non-zero exit value even on success,
11521193
// so checking for exitValue non-zero and stderr not empty for failure, otherwise its success
11531194

11541195
assertFalse(result.exitValue() != 0 && result.stderr() != null && !result.stderr().isEmpty(),
11551196
String.format("Command %s failed with exit value %s, stderr %s, stdout %s",
11561197
commandToExecuteInsidePod, result.exitValue(), result.stderr(), result.stdout()));
11571198

1199+
return true;
11581200
}
11591201

11601202
}

kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-domain-admin.tpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,7 @@ rules:
4040
- apiGroups: ["weblogic.oracle"]
4141
resources: ["domains/status", "clusters/status"]
4242
verbs: ["get", "watch"]
43+
- apiGroups: ["weblogic.oracle"]
44+
resources: ["clusters/scale"]
45+
verbs: ["update", "patch"]
4346
{{- end }}

kubernetes/charts/weblogic-operator/templates/_operator-clusterrole-general.tpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ rules:
3333
- apiGroups: ["weblogic.oracle"]
3434
resources: ["domains", "clusters", "domains/status", "clusters/status"]
3535
verbs: ["get", "create", "list", "watch", "update", "patch"]
36+
- apiGroups: ["weblogic.oracle"]
37+
resources: ["clusters/scale"]
38+
verbs: ["update", "patch"]
3639
- apiGroups: ["authentication.k8s.io"]
3740
resources: ["tokenreviews"]
3841
verbs: ["create"]

kubernetes/charts/weblogic-operator/templates/_operator-role.tpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@ rules:
2323
- apiGroups: ["weblogic.oracle"]
2424
resources: ["domains", "clusters"]
2525
verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"]
26+
- apiGroups: ["weblogic.oracle"]
27+
resources: ["domains/status", "clusters/status"]
28+
verbs: ["get", "watch"]
29+
- apiGroups: ["weblogic.oracle"]
30+
resources: ["clusters/scale"]
31+
verbs: ["update", "patch"]
2632
{{- end }}

0 commit comments

Comments
 (0)