From d511ce9ed89d80fc4966971beaf25bad84ee01ba Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Thu, 21 Jun 2018 17:57:48 +0530 Subject: [PATCH 01/24] Implement Kubernetes resources for WSO2 IS 5.6.0 pattern 1 --- .../{repository/conf => }/axis2/axis2.xml | 4 +- is/confs/bin/wso2server.sh | 318 ------------------ is/confs/{repository/conf => }/carbon.xml | 2 +- .../conf => }/consent-mgt-config.xml | 0 .../conf => }/datasources/bps-datasources.xml | 0 .../datasources/master-datasources.xml | 0 .../conf => }/hazelcast.properties | 0 .../conf => }/identity/identity.xml | 58 +++- .../{repository/conf => }/log4j.properties | 0 is/confs/{repository/conf => }/registry.xml | 0 is/confs/{repository/conf => }/user-mgt.xml | 0 .../confs/rdbms/mysql/dbscripts/init.sql | 39 +++ is/identity-server-deployment.yaml | 6 +- is/scripts/deploy.sh | 16 +- 14 files changed, 108 insertions(+), 335 deletions(-) rename is/confs/{repository/conf => }/axis2/axis2.xml (99%) delete mode 100644 is/confs/bin/wso2server.sh rename is/confs/{repository/conf => }/carbon.xml (99%) rename is/confs/{repository/conf => }/consent-mgt-config.xml (100%) rename is/confs/{repository/conf => }/datasources/bps-datasources.xml (100%) rename is/confs/{repository/conf => }/datasources/master-datasources.xml (100%) rename is/confs/{repository/conf => }/hazelcast.properties (100%) rename is/confs/{repository/conf => }/identity/identity.xml (94%) rename is/confs/{repository/conf => }/log4j.properties (100%) rename is/confs/{repository/conf => }/registry.xml (100%) rename is/confs/{repository/conf => }/user-mgt.xml (100%) diff --git a/is/confs/repository/conf/axis2/axis2.xml b/is/confs/axis2/axis2.xml similarity index 99% rename from is/confs/repository/conf/axis2/axis2.xml rename to is/confs/axis2/axis2.xml index 60db6c66..ee761786 100644 --- a/is/confs/repository/conf/axis2/axis2.xml +++ b/is/confs/axis2/axis2.xml @@ -73,10 +73,10 @@ axis2modules - WSO2 Identity Server-5.5.0 + WSO2 Identity Server-5.6.0 - WSO2 Identity Server-5.5.0 + WSO2 Identity Server-5.6.0 diff --git a/is/confs/bin/wso2server.sh b/is/confs/bin/wso2server.sh deleted file mode 100644 index a69d70d1..00000000 --- a/is/confs/bin/wso2server.sh +++ /dev/null @@ -1,318 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Copyright 2018 WSO2, Inc. http://www.wso2.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# ---------------------------------------------------------------------------- -# Main Script for the WSO2 Carbon Server -# -# Environment Variable Prequisites -# -# CARBON_HOME Home of WSO2 Carbon installation. If not set I will try -# to figure it out. -# -# JAVA_HOME Must point at your Java Development Kit installation. -# -# JAVA_OPTS (Optional) Java runtime options used when the commands -# is executed. -# -# NOTE: Borrowed generously from Apache Tomcat startup scripts. -# ----------------------------------------------------------------------------- - -# OS specific support. $var _must_ be set to either true or false. -#ulimit -n 100000 - -cygwin=false; -darwin=false; -os400=false; -mingw=false; -case "`uname`" in -CYGWIN*) cygwin=true;; -MINGW*) mingw=true;; -OS400*) os400=true;; -Darwin*) darwin=true - if [ -z "$JAVA_VERSION" ] ; then - JAVA_VERSION="CurrentJDK" - else - echo "Using Java version: $JAVA_VERSION" - fi - if [ -z "$JAVA_HOME" ] ; then - JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home - fi - ;; -esac - -# resolve links - $0 may be a softlink -PRG="$0" - -while [ -h "$PRG" ]; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '.*/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`/"$link" - fi -done - -# Get standard environment variables -PRGDIR=`dirname "$PRG"` - -# Only set CARBON_HOME if not already set -[ -z "$CARBON_HOME" ] && CARBON_HOME=`cd "$PRGDIR/.." ; pwd` - -# Set AXIS2_HOME. Needed for One Click JAR Download -AXIS2_HOME="$CARBON_HOME" - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CARBON_HOME" ] && CARBON_HOME=`cygpath --unix "$CARBON_HOME"` - [ -n "$AXIS2_HOME" ] && CARBON_HOME=`cygpath --unix "$CARBON_HOME"` -fi - -# For OS400 -if $os400; then - # Set job priority to standard for interactive (interactive - 6) by using - # the interactive priority - 6, the helper threads that respond to requests - # will be running at the same priority as interactive jobs. - COMMAND='chgjob job('$JOBNAME') runpty(6)' - system $COMMAND - - # Enable multi threading - QIBM_MULTI_THREADED=Y - export QIBM_MULTI_THREADED -fi - -# For Migwn, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$CARBON_HOME" ] && - CARBON_HOME="`(cd "$CARBON_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - [ -n "$AXIS2_HOME" ] && - CARBON_HOME="`(cd "$CARBON_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD=java - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." - echo " CARBON cannot execute $JAVACMD" - exit 1 -fi - -# if JAVA_HOME is not set we're not happy -if [ -z "$JAVA_HOME" ]; then - echo "You must set the JAVA_HOME variable before running CARBON." - exit 1 -fi - -if [ -e "$CARBON_HOME/wso2carbon.pid" ]; then - PID=`cat "$CARBON_HOME"/wso2carbon.pid` -fi - -# ----- Process the input command ---------------------------------------------- -args="" -for c in $* -do - if [ "$c" = "--debug" ] || [ "$c" = "-debug" ] || [ "$c" = "debug" ]; then - CMD="--debug" - continue - elif [ "$CMD" = "--debug" ]; then - if [ -z "$PORT" ]; then - PORT=$c - fi - elif [ "$c" = "--stop" ] || [ "$c" = "-stop" ] || [ "$c" = "stop" ]; then - CMD="stop" - elif [ "$c" = "--start" ] || [ "$c" = "-start" ] || [ "$c" = "start" ]; then - CMD="start" - elif [ "$c" = "--version" ] || [ "$c" = "-version" ] || [ "$c" = "version" ]; then - CMD="version" - elif [ "$c" = "--restart" ] || [ "$c" = "-restart" ] || [ "$c" = "restart" ]; then - CMD="restart" - elif [ "$c" = "--test" ] || [ "$c" = "-test" ] || [ "$c" = "test" ]; then - CMD="test" - else - args="$args $c" - fi -done - -if [ "$CMD" = "--debug" ]; then - if [ "$PORT" = "" ]; then - echo " Please specify the debug port after the --debug option" - exit 1 - fi - if [ -n "$JAVA_OPTS" ]; then - echo "Warning !!!. User specified JAVA_OPTS will be ignored, once you give the --debug option." - fi - CMD="RUN" - JAVA_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=$PORT" - echo "Please start the remote debugging client to continue..." -elif [ "$CMD" = "start" ]; then - if [ -e "$CARBON_HOME/wso2carbon.pid" ]; then - if ps -p $PID > /dev/null ; then - echo "Process is already running" - exit 0 - fi - fi - export CARBON_HOME="$CARBON_HOME" -# using nohup sh to avoid erros in solaris OS.TODO - nohup sh "$CARBON_HOME"/bin/wso2server.sh $args > /dev/null 2>&1 & - exit 0 -elif [ "$CMD" = "stop" ]; then - export CARBON_HOME="$CARBON_HOME" - kill -term `cat "$CARBON_HOME"/wso2carbon.pid` - exit 0 -elif [ "$CMD" = "restart" ]; then - export CARBON_HOME="$CARBON_HOME" - kill -term `cat "$CARBON_HOME"/wso2carbon.pid` - process_status=0 - pid=`cat "$CARBON_HOME"/wso2carbon.pid` - while [ "$process_status" -eq "0" ] - do - sleep 1; - ps -p$pid 2>&1 > /dev/null - process_status=$? - done - -# using nohup sh to avoid erros in solaris OS.TODO - nohup sh "$CARBON_HOME"/bin/wso2server.sh $args > /dev/null 2>&1 & - exit 0 -elif [ "$CMD" = "test" ]; then - JAVACMD="exec "$JAVACMD"" -elif [ "$CMD" = "version" ]; then - cat "$CARBON_HOME"/bin/version.txt - cat "$CARBON_HOME"/bin/wso2carbon-version.txt - exit 0 -fi - -# ---------- Handle the SSL Issue with proper JDK version -------------------- -jdk_17=`$JAVA_HOME/bin/java -version 2>&1 | grep "1.[7|8]"` -if [ "$jdk_17" = "" ]; then - echo " Starting WSO2 Carbon (in unsupported JDK)" - echo " [ERROR] CARBON is supported only on JDK 1.7 and 1.8" -fi - -CARBON_XBOOTCLASSPATH="" -for f in "$CARBON_HOME"/lib/xboot/*.jar -do - if [ "$f" != "$CARBON_HOME/lib/xboot/*.jar" ];then - CARBON_XBOOTCLASSPATH="$CARBON_XBOOTCLASSPATH":$f - fi -done - -JAVA_ENDORSED_DIRS="$CARBON_HOME/lib/endorsed":"$JAVA_HOME/jre/lib/endorsed":"$JAVA_HOME/lib/endorsed" - -CARBON_CLASSPATH="" -if [ -e "$JAVA_HOME/lib/tools.jar" ]; then - CARBON_CLASSPATH="$JAVA_HOME/lib/tools.jar" -fi -for f in "$CARBON_HOME"/bin/*.jar -do - if [ "$f" != "$CARBON_HOME/bin/*.jar" ];then - CARBON_CLASSPATH="$CARBON_CLASSPATH":$f - fi -done -for t in "$CARBON_HOME"/lib/commons-lang*.jar -do - CARBON_CLASSPATH="$CARBON_CLASSPATH":$t -done -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - JAVA_HOME=`cygpath --absolute --windows "$JAVA_HOME"` - CARBON_HOME=`cygpath --absolute --windows "$CARBON_HOME"` - AXIS2_HOME=`cygpath --absolute --windows "$CARBON_HOME"` - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"` - CARBON_CLASSPATH=`cygpath --path --windows "$CARBON_CLASSPATH"` - CARBON_XBOOTCLASSPATH=`cygpath --path --windows "$CARBON_XBOOTCLASSPATH"` -fi - -# ----- Execute The Requested Command ----------------------------------------- - -echo JAVA_HOME environment variable is set to $JAVA_HOME -echo CARBON_HOME environment variable is set to "$CARBON_HOME" - -cd "$CARBON_HOME" - -TMP_DIR="$CARBON_HOME"/tmp -if [ -d "$TMP_DIR" ]; then -rm -rf "$TMP_DIR"/* -fi - -START_EXIT_STATUS=121 -status=$START_EXIT_STATUS - -if [ -z "$JVM_MEM_OPTS" ]; then - java_version=$("$JAVACMD" -version 2>&1 | awk -F '"' '/version/ {print $2}') - JVM_MEM_OPTS="-Xms256m -Xmx1024m" - if [ "$java_version" \< "1.8" ]; then - JVM_MEM_OPTS="$JVM_MEM_OPTS -XX:MaxPermSize=256m" - fi -fi -echo "Using Java memory options: $JVM_MEM_OPTS" - -#To monitor a Carbon server in remote JMX mode on linux host machines, set the below system property. -# -Djava.rmi.server.hostname="your.IP.goes.here" - -while [ "$status" = "$START_EXIT_STATUS" ] -do - $JAVACMD \ - -Xbootclasspath/a:"$CARBON_XBOOTCLASSPATH" \ - $JVM_MEM_OPTS \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:HeapDumpPath="$CARBON_HOME/repository/logs/heap-dump.hprof" \ - $JAVA_OPTS \ - -Dcom.sun.management.jmxremote \ - -classpath "$CARBON_CLASSPATH" \ - -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \ - -Djava.io.tmpdir="$CARBON_HOME/tmp" \ - -Dcatalina.base="$CARBON_HOME/lib/tomcat" \ - -Dwso2.server.standalone=true \ - -Dcarbon.registry.root=/ \ - -Djava.command="$JAVACMD" \ - -Dcarbon.home="$CARBON_HOME" \ - -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \ - -Dcarbon.config.dir.path="$CARBON_HOME/repository/conf" \ - -Djava.util.logging.config.file="$CARBON_HOME/repository/conf/etc/logging-bridge.properties" \ - -Dcomponents.repo="$CARBON_HOME/repository/components/plugins" \ - -Dconf.location="$CARBON_HOME/repository/conf"\ - -Dcom.atomikos.icatch.file="$CARBON_HOME/lib/transactions.properties" \ - -Dcom.atomikos.icatch.hide_init_file_path=true \ - -Dorg.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false \ - -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true \ - -Dcom.sun.jndi.ldap.connect.pool.authentication=simple \ - -Dcom.sun.jndi.ldap.connect.pool.timeout=3000 \ - -Dorg.terracotta.quartz.skipUpdateCheck=true \ - -Djava.security.egd=file:/dev/./urandom \ - -Dfile.encoding=UTF8 \ - -Djava.net.preferIPv4Stack=true \ - -Dcom.ibm.cacheLocalHost=true \ - -DworkerNode=false \ - org.wso2.carbon.bootstrap.Bootstrap $* - status=$? -done diff --git a/is/confs/repository/conf/carbon.xml b/is/confs/carbon.xml similarity index 99% rename from is/confs/repository/conf/carbon.xml rename to is/confs/carbon.xml index 4b6abd0f..1b35fb7b 100644 --- a/is/confs/repository/conf/carbon.xml +++ b/is/confs/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 + true + + 20 + + 40 + @@ -189,6 +199,12 @@ true org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor + + false false @@ -603,13 +619,14 @@ + - + orderId="90" enable="false"/> + orderId="93" enable="true"/> @@ -634,6 +651,21 @@ + + + + + + + + + 300 + + + true + + 1000 + 1000 + 51200 + + + + + + http://localhost:8280/ + + 5 + + diff --git a/is/confs/repository/conf/log4j.properties b/is/confs/log4j.properties similarity index 100% rename from is/confs/repository/conf/log4j.properties rename to is/confs/log4j.properties diff --git a/is/confs/repository/conf/registry.xml b/is/confs/registry.xml similarity index 100% rename from is/confs/repository/conf/registry.xml rename to is/confs/registry.xml diff --git a/is/confs/repository/conf/user-mgt.xml b/is/confs/user-mgt.xml similarity index 100% rename from is/confs/repository/conf/user-mgt.xml rename to is/confs/user-mgt.xml diff --git a/is/extras/confs/rdbms/mysql/dbscripts/init.sql b/is/extras/confs/rdbms/mysql/dbscripts/init.sql index 906b5bf7..44665e4f 100644 --- a/is/extras/confs/rdbms/mysql/dbscripts/init.sql +++ b/is/extras/confs/rdbms/mysql/dbscripts/init.sql @@ -540,6 +540,7 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_CONSUMER_APPS ( USER_ACCESS_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600000, APP_ACCESS_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600000, REFRESH_TOKEN_EXPIRE_TIME BIGINT DEFAULT 84600000, + ID_TOKEN_EXPIRE_TIME BIGINT DEFAULT 3600000, CONSTRAINT CONSUMER_KEY_CONSTRAINT UNIQUE (CONSUMER_KEY), PRIMARY KEY (ID) )ENGINE INNODB; @@ -608,6 +609,9 @@ CREATE INDEX IDX_TC ON IDN_OAUTH2_ACCESS_TOKEN(TIME_CREATED); CREATE INDEX IDX_ATH ON IDN_OAUTH2_ACCESS_TOKEN(ACCESS_TOKEN_HASH); +CREATE INDEX IDX_AT_TI_UD ON IDN_OAUTH2_ACCESS_TOKEN(AUTHZ_USER, TENANT_ID, TOKEN_STATE, USER_DOMAIN); + + CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_CODE ( CODE_ID VARCHAR (255), AUTHORIZATION_CODE VARCHAR(2048), @@ -631,6 +635,9 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH2_AUTHORIZATION_CODE ( CREATE INDEX IDX_AUTHORIZATION_CODE_HASH ON IDN_OAUTH2_AUTHORIZATION_CODE (AUTHORIZATION_CODE_HASH,CONSUMER_KEY_ID); +CREATE INDEX IDX_AUTHORIZATION_CODE_AU_TI ON IDN_OAUTH2_AUTHORIZATION_CODE (AUTHZ_USER,TENANT_ID, USER_DOMAIN, STATE); + + CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_SCOPE ( TOKEN_ID VARCHAR (255), TOKEN_SCOPE VARCHAR (60), @@ -671,6 +678,11 @@ CREATE TABLE IF NOT EXISTS IDN_SCIM_GROUP ( PRIMARY KEY (ID) )ENGINE INNODB; +CREATE INDEX IDX_IDN_SCIM_GROUP_TI_RN ON IDN_SCIM_GROUP (TENANT_ID, ROLE_NAME); + +CREATE INDEX IDX_IDN_SCIM_GROUP_TI_RN_AN ON IDN_SCIM_GROUP (TENANT_ID, ROLE_NAME, ATTR_NAME); + + CREATE TABLE IF NOT EXISTS IDN_OPENID_REMEMBER_ME ( USER_NAME VARCHAR(255) NOT NULL, TENANT_ID INTEGER DEFAULT 0, @@ -743,9 +755,27 @@ CREATE TABLE IF NOT EXISTS IDN_AUTH_SESSION_STORE ( SESSION_OBJECT BLOB, TIME_CREATED BIGINT, TENANT_ID INTEGER DEFAULT -1, + EXPIRY_TIME BIGINT, + PRIMARY KEY (SESSION_ID, SESSION_TYPE, TIME_CREATED, OPERATION) +)ENGINE INNODB; + +CREATE INDEX IDX_IDN_AUTH_SESSION_STORE_TIME ON IDN_AUTH_SESSION_STORE (TIME_CREATED); + + +CREATE TABLE IF NOT EXISTS IDN_AUTH_TEMP_SESSION_STORE ( + SESSION_ID VARCHAR (100) NOT NULL, + SESSION_TYPE VARCHAR(100) NOT NULL, + OPERATION VARCHAR(10) NOT NULL, + SESSION_OBJECT BLOB, + TIME_CREATED BIGINT, + TENANT_ID INTEGER DEFAULT -1, + EXPIRY_TIME BIGINT, PRIMARY KEY (SESSION_ID, SESSION_TYPE, TIME_CREATED, OPERATION) )ENGINE INNODB; +CREATE INDEX IDX_IDN_AUTH_TEMP_SESSION_STORE_TIME ON IDN_AUTH_TEMP_SESSION_STORE (TIME_CREATED); + + CREATE TABLE IF NOT EXISTS SP_APP ( ID INTEGER NOT NULL AUTO_INCREMENT, TENANT_ID INTEGER NOT NULL, @@ -817,6 +847,15 @@ CREATE TABLE IF NOT EXISTS SP_FEDERATED_IDP ( ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE; +CREATE TABLE IF NOT EXISTS SP_CLAIM_DIALECT ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + SP_DIALECT VARCHAR (512) NOT NULL, + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_CLAIM_DIALECT ADD CONSTRAINT DIALECTID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + CREATE TABLE IF NOT EXISTS SP_CLAIM_MAPPING ( ID INTEGER NOT NULL AUTO_INCREMENT, TENANT_ID INTEGER NOT NULL, diff --git a/is/identity-server-deployment.yaml b/is/identity-server-deployment.yaml index 8c8f59db..0590ea4d 100644 --- a/is/identity-server-deployment.yaml +++ b/is/identity-server-deployment.yaml @@ -31,7 +31,7 @@ spec: spec: containers: - name: wso2is - image: docker.wso2.com/wso2is:5.5.0 + image: docker.wso2.com/wso2is:5.6.0 livenessProbe: exec: command: @@ -64,9 +64,9 @@ spec: - name: identity-server-conf-identity mountPath: /home/wso2carbon/kubernetes-volumes/is/conf-identity - name: shared-deployment-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/deployment + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/deployment - name: shared-tenants-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/tenants + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/tenants serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds diff --git a/is/scripts/deploy.sh b/is/scripts/deploy.sh index 1ee0754e..5f1509e9 100755 --- a/is/scripts/deploy.sh +++ b/is/scripts/deploy.sh @@ -49,13 +49,13 @@ while [ "$1" != "" ]; do usage exit 1 ;; - --free-trial-username) + --free-trial-username | --ftu) FT_USERNAME=$VALUE ;; - --free-trial-password) + --free-trial-password | --ftp) FT_PASSWORD=$VALUE ;; - --cluster-admin-password) + --cluster-admin-password | --cap) ADMIN_PASSWORD=$VALUE ;; *) @@ -77,17 +77,17 @@ ${KUBECTL} create serviceaccount wso2svc-account -n wso2 ${KUBECTL} config set-context $(kubectl config current-context) --namespace=wso2 # create a Kubernetes Secret for passing WSO2 Private Docker Registry credentials -${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} +#${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} # create Kubernetes Role and Role Binding necessary for the Kubernetes API requests made from Kubernetes membership scheme ${KUBECTL} create --username=admin --password=${ADMIN_PASSWORD} -f ../../rbac/rbac.yaml # create Kubernetes ConfigMaps echoBold 'Creating Kubernetes ConfigMaps...' -${KUBECTL} create configmap identity-server-conf --from-file=../confs/repository/conf/ -${KUBECTL} create configmap identity-server-conf-axis2 --from-file=../confs/repository/conf/axis2/ -${KUBECTL} create configmap identity-server-conf-datasources --from-file=../confs/repository/conf/datasources/ -${KUBECTL} create configmap identity-server-conf-identity --from-file=../confs/repository/conf/identity/ +${KUBECTL} create configmap identity-server-conf --from-file=../confs/ +${KUBECTL} create configmap identity-server-conf-axis2 --from-file=../confs/axis2/ +${KUBECTL} create configmap identity-server-conf-datasources --from-file=../confs/datasources/ +${KUBECTL} create configmap identity-server-conf-identity --from-file=../confs/identity/ ${KUBECTL} create configmap mysql-dbscripts --from-file=../extras/confs/rdbms/mysql/dbscripts/ echoBold 'Deploying the Kubernetes Services...' From 1be3786c4992cfdbb83635f716ed7420e031da01 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 15:58:08 +0530 Subject: [PATCH 02/24] Migrate IS pattern 2 Kubernetes resources to version 5.6.0 --- is-with-analytics/README.md | 33 ++-- .../confs/is-analytics-1/conf/axis2/axis2.xml | 4 +- .../confs/is-analytics-1/conf/carbon.xml | 2 +- .../confs/is-analytics-2/conf/axis2/axis2.xml | 4 +- .../confs/is-analytics-2/conf/carbon.xml | 2 +- .../confs/is/conf/axis2/axis2.xml | 4 +- is-with-analytics/confs/is/conf/carbon.xml | 2 +- .../confs/is/conf/identity/identity.xml | 58 ++++++- ...Analytics-Publisher-wso2event-RoleData.xml | 41 +++-- ...Analytics-Publisher-wso2event-UserData.xml | 41 +++-- .../confs/rdbms/mysql/dbscripts/init.sql | 0 .../rdbms/mysql/mysql-deployment.yaml | 0 .../rdbms/mysql/mysql-service.yaml | 0 ...dentity-server-analytics-1-deployment.yaml | 9 +- ...dentity-server-analytics-2-deployment.yaml | 9 +- ...entity-server-analytics-volume-claims.yaml | 40 ++++- is-with-analytics/is-with-analytics.png | Bin 0 -> 82744 bytes .../is/identity-server-deployment.yaml | 6 +- is-with-analytics/{test => scripts}/README.md | 51 +++---- is-with-analytics/scripts/deploy.sh | 143 ++++++++++++++++++ is-with-analytics/scripts/undeploy.sh | 57 +++++++ is-with-analytics/test/deploy.sh | 95 ------------ is-with-analytics/test/undeploy.sh | 34 ----- .../volumes/persistent-volumes.yaml | 40 ++++- 24 files changed, 459 insertions(+), 216 deletions(-) rename is-with-analytics/{test => extras}/confs/rdbms/mysql/dbscripts/init.sql (100%) rename is-with-analytics/{test => extras}/rdbms/mysql/mysql-deployment.yaml (100%) rename is-with-analytics/{test => extras}/rdbms/mysql/mysql-service.yaml (100%) create mode 100644 is-with-analytics/is-with-analytics.png rename is-with-analytics/{test => scripts}/README.md (78%) create mode 100755 is-with-analytics/scripts/deploy.sh create mode 100755 is-with-analytics/scripts/undeploy.sh delete mode 100755 is-with-analytics/test/deploy.sh delete mode 100755 is-with-analytics/test/undeploy.sh diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index 1c671990..c8029407 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -2,18 +2,20 @@ Core Kubernetes resources for a clustered deployment of WSO2 Identity Server with WSO2 Identity Server Analytics. +![A clustered deployment WSO2 Identity Server with Identity Server Analytics support](is-with-analytics.png) + ## Prerequisites * In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server. -You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server and +Identity Server Analytics. You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) (version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) in order to run the steps provided
in the following quick start guide.

* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/)

- + ## Quick Start Guide >In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) @@ -43,12 +45,11 @@ kubectl config set-context $(kubectl config current-context) --namespace=wso2 Create a Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. ``` -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= +kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= ``` -`username`: Username of your Free Trial Subscription
-`password`: Password of your Free Trial Subscription
-`email`: Docker email +`FT_USERNAME`: Username of your Free Trial Subscription
+`FT_PASSWORD`: Password of your Free Trial Subscription Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. @@ -73,7 +74,7 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN **Note**: * For **evaluation purposes**, you can use Kubernetes resources provided in the directory
-`KUBERNETES_HOME/is-with-analytics/test/rdbms/mysql` for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is +`KUBERNETES_HOME/is-with-analytics/extras/rdbms/mysql` for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is **not recommended** for a production setup. * For using these Kubernetes resources, @@ -81,22 +82,24 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN first create a Kubernetes ConfigMap for passing database script(s) to the deployment. ``` - kubectl create configmap mysql-dbscripts --from-file=/is-with-analytics/test/confs/mysql/dbscripts/ + kubectl create configmap mysql-dbscripts --from-file=/is-with-analytics/extras/confs/mysql/dbscripts/ ``` Then, create a Kubernetes service (accessible only within the Kubernetes cluster) and followed by the MySQL Kubernetes deployment, as follows: ``` - kubectl create -f /is-with-analytics/test/rdbms/mysql/mysql-service.yaml - kubectl create -f /is-with-analytics/test/rdbms/mysql/mysql-deployment.yaml + kubectl create -f /is-with-analytics/extras/rdbms/mysql/mysql-service.yaml + kubectl create -f /is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml ``` ##### 5. Create a Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. ``` -kubectl create --username=admin --password= -f /rbac/rbac.yaml +kubectl create --username=admin --password= -f /rbac/rbac.yaml ``` +`K8S_CLUSTER_ADMIN_PASSWORD`: Kubernetes cluster admin password + ##### 6. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resources, @@ -105,6 +108,8 @@ Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) * `wso2is-with-analytics-shared-tenants-pv` * `wso2is-with-analytics-is-analytics-data-pv-1` * `wso2is-with-analytics-is-analytics-data-pv-2` +* `wso2is-with-analytics-is-analytics-pv-1` +* `wso2is-with-analytics-is-analytics-pv-2` in `/is-with-analytics/volumes/persistent-volumes.yaml` file. @@ -160,12 +165,12 @@ kubectl create -f /is-with-analytics/is-analytics/identity-serv ##### 9. Deploy Kubernetes Ingress resource: -The WSO2 Identity Server Kubernetes Ingress resource uses the NGINX Ingress Controller. +The WSO2 Identity Server and Identity Server Analytics Kubernetes Ingress resources use the NGINX Ingress Controller. In order to enable the NGINX Ingress controller in the desired cloud or on-premise environment, please refer the official documentation, [NGINX Ingress Controller Installation Guide](https://kubernetes.github.io/ingress-nginx/deploy/). -Finally, deploy the WSO2 Identity Server Kubernetes Ingress resources as follows: +Finally, deploy the WSO2 Identity Server and Identity Server Analytics Kubernetes Ingress resources as follows: ``` kubectl create -f /is-with-analytics/ingresses/identity-server-ingress.yaml diff --git a/is-with-analytics/confs/is-analytics-1/conf/axis2/axis2.xml b/is-with-analytics/confs/is-analytics-1/conf/axis2/axis2.xml index 5f15064a..dc770b2e 100644 --- a/is-with-analytics/confs/is-analytics-1/conf/axis2/axis2.xml +++ b/is-with-analytics/confs/is-analytics-1/conf/axis2/axis2.xml @@ -73,10 +73,10 @@ axis2modules - WSO2 Identity Server Analytics-5.5.0 + WSO2 Identity Server Analytics-5.6.0 - WSO2 Identity Server Analytics-5.5.0 + WSO2 Identity Server Analytics-5.6.0 diff --git a/is-with-analytics/confs/is-analytics-1/conf/carbon.xml b/is-with-analytics/confs/is-analytics-1/conf/carbon.xml index 79ff505f..50bb5910 100644 --- a/is-with-analytics/confs/is-analytics-1/conf/carbon.xml +++ b/is-with-analytics/confs/is-analytics-1/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 diff --git a/is-with-analytics/confs/is-analytics-2/conf/carbon.xml b/is-with-analytics/confs/is-analytics-2/conf/carbon.xml index 79ff505f..50bb5910 100644 --- a/is-with-analytics/confs/is-analytics-2/conf/carbon.xml +++ b/is-with-analytics/confs/is-analytics-2/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 diff --git a/is-with-analytics/confs/is/conf/carbon.xml b/is-with-analytics/confs/is/conf/carbon.xml index 4b6abd0f..1b35fb7b 100644 --- a/is-with-analytics/confs/is/conf/carbon.xml +++ b/is-with-analytics/confs/is/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 + true + + 20 + + 40 + @@ -189,6 +199,12 @@ true org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor + + false false @@ -603,13 +619,14 @@ + - + orderId="90" enable="false"/> + orderId="93" enable="true"/> @@ -634,6 +651,21 @@ + + + + + + + + + 300 + + + true + + 1000 + 1000 + 51200 + + + + + + http://localhost:8280/ + + 5 + + diff --git a/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml b/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml index 1ed4d0c2..29c9cc95 100644 --- a/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml +++ b/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml @@ -1,13 +1,32 @@ - - - - - admin - thrift - non-blocking - 0 - tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 - admin - + + + + + + + admin + thrift + non-blocking + 0 + tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 + admin + diff --git a/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml b/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml index 2b9b97ac..a6021d71 100644 --- a/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml +++ b/is-with-analytics/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml @@ -1,13 +1,32 @@ - - - - - admin - thrift - non-blocking - 0 - tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 - admin - + + + + + + + admin + thrift + non-blocking + 0 + tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 + admin + diff --git a/is-with-analytics/test/confs/rdbms/mysql/dbscripts/init.sql b/is-with-analytics/extras/confs/rdbms/mysql/dbscripts/init.sql similarity index 100% rename from is-with-analytics/test/confs/rdbms/mysql/dbscripts/init.sql rename to is-with-analytics/extras/confs/rdbms/mysql/dbscripts/init.sql diff --git a/is-with-analytics/test/rdbms/mysql/mysql-deployment.yaml b/is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml similarity index 100% rename from is-with-analytics/test/rdbms/mysql/mysql-deployment.yaml rename to is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml diff --git a/is-with-analytics/test/rdbms/mysql/mysql-service.yaml b/is-with-analytics/extras/rdbms/mysql/mysql-service.yaml similarity index 100% rename from is-with-analytics/test/rdbms/mysql/mysql-service.yaml rename to is-with-analytics/extras/rdbms/mysql/mysql-service.yaml diff --git a/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml b/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml index bc7315fc..ccca50a5 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-1 - image: docker.wso2.com/wso2is-analytics:5.5.0 + image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" @@ -126,8 +126,10 @@ spec: mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-datasources - name: is-analytics-1-deployment-portal mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-portal + - name: analytics-persistent-disk + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/conf/analytics - name: data-persistent-disk - mountPath: /home/wso2carbon/wso2is-analytics-5.5.0/repository/data + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/data serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds @@ -150,6 +152,9 @@ spec: - name: is-analytics-1-deployment-portal configMap: name: is-analytics-1-deployment-portal + - name: analytics-persistent-disk + persistentVolumeClaim: + claimName: is-analytics-1-analytics-volume-claim - name: data-persistent-disk persistentVolumeClaim: claimName: is-analytics-1-data-volume-claim diff --git a/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml b/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml index b2645708..7fab7f6d 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-2 - image: docker.wso2.com/wso2is-analytics:5.5.0 + image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" @@ -126,8 +126,10 @@ spec: mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-datasources - name: is-analytics-2-deployment-portal mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-portal + - name: analytics-persistent-disk + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/conf/analytics - name: data-persistent-disk - mountPath: /home/wso2carbon/wso2is-analytics-5.5.0/repository/data + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/data serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds @@ -150,6 +152,9 @@ spec: - name: is-analytics-2-deployment-portal configMap: name: is-analytics-2-deployment-portal + - name: analytics-persistent-disk + persistentVolumeClaim: + claimName: is-analytics-2-analytics-volume-claim - name: data-persistent-disk persistentVolumeClaim: claimName: is-analytics-2-data-volume-claim diff --git a/is-with-analytics/is-analytics/identity-server-analytics-volume-claims.yaml b/is-with-analytics/is-analytics/identity-server-analytics-volume-claims.yaml index 3d2c8424..e6f2bed5 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-volume-claims.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-volume-claims.yaml @@ -21,7 +21,7 @@ spec: - ReadWriteMany resources: requests: - storage: 1Gi + storage: 20Gi storageClassName: "" selector: matchLabels: @@ -39,9 +39,45 @@ spec: - ReadWriteMany resources: requests: - storage: 1Gi + storage: 20Gi storageClassName: "" selector: matchLabels: purpose: analytics-data node: wso2is-analytics-2 + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: is-analytics-1-analytics-volume-claim +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: "" + selector: + matchLabels: + purpose: analytics + node: wso2is-analytics-1 + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: is-analytics-2-analytics-volume-claim +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: "" + selector: + matchLabels: + purpose: analytics + node: wso2is-analytics-2 diff --git a/is-with-analytics/is-with-analytics.png b/is-with-analytics/is-with-analytics.png new file mode 100644 index 0000000000000000000000000000000000000000..5799becd4f92e5ae72d3b4e1a9b736bcc17426a7 GIT binary patch literal 82744 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 z

+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 z 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 P%cOis{bKg{TMz#S!HXX{ literal 0 HcmV?d00001 diff --git a/is-with-analytics/is/identity-server-deployment.yaml b/is-with-analytics/is/identity-server-deployment.yaml index ecc185c3..addb8a90 100644 --- a/is-with-analytics/is/identity-server-deployment.yaml +++ b/is-with-analytics/is/identity-server-deployment.yaml @@ -31,7 +31,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is - image: docker.wso2.com/wso2is:5.5.0 + image: gcr.io/apim3-177506/wso2is:5.6.0 livenessProbe: exec: command: @@ -66,9 +66,9 @@ spec: - name: identity-server-conf-event-publishers mountPath: /home/wso2carbon/kubernetes-volumes/is/conf-event-publishers - name: shared-deployment-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/deployment + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/deployment - name: shared-tenants-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/tenants + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/tenants serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds diff --git a/is-with-analytics/test/README.md b/is-with-analytics/scripts/README.md similarity index 78% rename from is-with-analytics/test/README.md rename to is-with-analytics/scripts/README.md index 807ccc3b..396027a0 100644 --- a/is-with-analytics/test/README.md +++ b/is-with-analytics/scripts/README.md @@ -6,8 +6,8 @@ Kubernetes resources provided for a clustered deployment of WSO2 Identity Server ## Prerequisites * In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server. -You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server and +Identity Server Analytics. You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) (version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) @@ -33,31 +33,14 @@ The WSO2 Identity Server Kubernetes Ingress resource uses the NGINX Ingress Cont In order to enable the NGINX Ingress controller in the desired cloud or on-premise environment, please refer the official documentation, [NGINX Ingress Controller Installation Guide](https://kubernetes.github.io/ingress-nginx/deploy/). -##### 3. Update the deploy.sh file with the [`WSO2 Docker Registry`](https://docker.wso2.com) credentials and Kubernetes cluster admin password. - -Replace the relevant placeholders in `KUBERNETES_HOME/is-with-analytics//test/deploy.sh` file with appropriate details, as described below. - -* A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. -The following details need to be replaced in the relevant command. - -``` -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= -``` - -`username`: Username of your Free Trial Subscription
-`password`: Password of your Free Trial Subscription
-`email`: Docker email - -* A Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. - -`cluster-admin-password`: Kubernetes cluster admin password - -##### 4. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. +##### 3. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resources, * `wso2is-with-analytics-shared-deployment-pv` * `wso2is-with-analytics-shared-tenants-pv` +* `wso2is-with-analytics-is-analytics-pv-1` +* `wso2is-with-analytics-is-analytics-pv-2` * `wso2is-with-analytics-is-analytics-data-pv-1` * `wso2is-with-analytics-is-analytics-data-pv-2` @@ -68,17 +51,28 @@ Add `wso2carbon` user to the group `wso2`. Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. - -##### 5. Deploy Kubernetes test resources: -Change directory to `KUBERNETES_HOME/is-with-analytics/test` and execute the `deploy.sh` shell script on the terminal. +##### 4. Deploy Kubernetes resources: + +Change directory to `KUBERNETES_HOME/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh +./deploy.sh --free-trial-username= --free-trial-password= --cluster-admin-password= ``` + +* A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. +The following details need to be replaced in the relevant command. + +`FT_USERNAME`: Username of your Free Trial Subscription
+`FT_PASSWORD`: Password of your Free Trial Subscription + +* A Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. + +`K8S_CLUSTER_ADMIN_PASSWORD`: Kubernetes cluster admin password + >To un-deploy, be on the same directory and execute the `undeploy.sh` shell script on the terminal. -##### 6. Access Management Consoles: +##### 5. Access Management Consoles: Default deployment will expose `wso2is` and `wso2is-analytics` hosts (to expose Administrative services and Management Console). @@ -103,7 +97,7 @@ wso2is-with-analytics-is-ingress wso2is 3. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. -##### 7. Scale up using `kubectl scale`: +##### 6. Scale up using `kubectl scale`: Default deployment runs two replicas (or pods) of WSO2 Identity server. To scale this deployment into any `` number of container replicas, upon your requirement, simply run following Kubernetes client command on the terminal. @@ -113,4 +107,3 @@ kubectl scale --replicas= -f /is/identity-server-deployment. ``` For example, If `` is 2, you are here scaling up this deployment from 1 to 2 container replicas. - diff --git a/is-with-analytics/scripts/deploy.sh b/is-with-analytics/scripts/deploy.sh new file mode 100755 index 00000000..d857899a --- /dev/null +++ b/is-with-analytics/scripts/deploy.sh @@ -0,0 +1,143 @@ +#!/bin/bash + +# ------------------------------------------------------------------------ +# Copyright 2018 WSO2, Inc. (http://wso2.com) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License +# ------------------------------------------------------------------------ + +set -e + +ECHO=`which echo` +KUBECTL=`which kubectl` + +# methods +function echoBold () { + ${ECHO} -e $'\e[1m'"${1}"$'\e[0m' +} + +function usage () { + echoBold "This script automates the installation of WSO2 Identity Server pattern 1 Kubernetes resources\n" + echoBold "Allowed arguments:\n" + echoBold "-h | --help" + echoBold "--free-trial-username\t\tYour WSO2 Free Trial username" + echoBold "--free-trial-password\t\tYour WSO2 Free Trial password" + echoBold "--cluster-admin-password\tKubernetes cluster admin password\n\n" +} + +FT_USERNAME='' +FT_PASSWORD='' +ADMIN_PASSWORD='' + +# capture named arguments +while [ "$1" != "" ]; do + PARAM=`echo $1 | awk -F= '{print $1}'` + VALUE=`echo $1 | awk -F= '{print $2}'` + + case $PARAM in + -h | --help) + usage + exit 1 + ;; + --free-trial-username) + FT_USERNAME=$VALUE + ;; + --free-trial-password) + FT_PASSWORD=$VALUE + ;; + --cluster-admin-password) + ADMIN_PASSWORD=$VALUE + ;; + *) + echoBold "ERROR: unknown parameter \"$PARAM\"" + usage + exit 1 + ;; + esac + shift +done + +# create a new Kubernetes Namespace +${KUBECTL} create namespace wso2 + +# create a new service account in 'wso2' Kubernetes Namespace +${KUBECTL} create serviceaccount wso2svc-account -n wso2 + +# switch the context to new 'wso2' namespace +${KUBECTL} config set-context $(${KUBECTL} config current-context) --namespace=wso2 + +# create a Kubernetes Secret for passing WSO2 Private Docker Registry credentials +${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} + +# create Kubernetes Role and Role Binding necessary for the Kubernetes API requests made from Kubernetes membership scheme +${KUBECTL} create --username=admin --password=${ADMIN_PASSWORD} -f ../../rbac/rbac.yaml + +# create Kubernetes ConfigMaps +echoBold 'Creating ConfigMaps...' +${KUBECTL} create configmap identity-server-conf --from-file=../confs/is/conf/ +${KUBECTL} create configmap identity-server-conf-axis2 --from-file=../confs/is/conf/axis2/ +${KUBECTL} create configmap identity-server-conf-datasources --from-file=../confs/is/conf/datasources/ +${KUBECTL} create configmap identity-server-conf-identity --from-file=../confs/is/conf/identity/ +${KUBECTL} create configmap identity-server-conf-event-publishers --from-file=../confs/is/deployment/server/eventpublishers/ + +${KUBECTL} create configmap is-analytics-1-conf --from-file=../confs/is-analytics-1/conf +${KUBECTL} create configmap is-analytics-1-conf-analytics --from-file=../confs/is-analytics-1/conf/analytics +${KUBECTL} create configmap is-analytics-1-conf-spark-analytics --from-file=../confs/is-analytics-1/conf/analytics/spark +${KUBECTL} create configmap is-analytics-1-conf-axis2 --from-file=../confs/is-analytics-1/conf/axis2 +${KUBECTL} create configmap is-analytics-1-conf-datasources --from-file=../confs/is-analytics-1/conf/datasources +${KUBECTL} create configmap is-analytics-1-deployment-portal --from-file=../confs/is-analytics-1/deployment/server/jaggeryapps/portal/configs + +${KUBECTL} create configmap is-analytics-2-conf --from-file=../confs/is-analytics-2/conf +${KUBECTL} create configmap is-analytics-2-conf-analytics --from-file=../confs/is-analytics-2/conf/analytics +${KUBECTL} create configmap is-analytics-2-conf-spark-analytics --from-file=../confs/is-analytics-2/conf/analytics/spark +${KUBECTL} create configmap is-analytics-2-conf-axis2 --from-file=../confs/is-analytics-2/conf/axis2 +${KUBECTL} create configmap is-analytics-2-conf-datasources --from-file=../confs/is-analytics-2/conf/datasources +${KUBECTL} create configmap is-analytics-2-deployment-portal --from-file=../confs/is-analytics-2/deployment/server/jaggeryapps/portal/configs + +${KUBECTL} create configmap mysql-dbscripts --from-file=../extras/confs/rdbms/mysql/dbscripts/ + +echoBold 'Deploying the Kubernetes Services...' +${KUBECTL} create -f ../extras/rdbms/mysql/mysql-service.yaml +${KUBECTL} create -f ../is/identity-server-service.yaml +${KUBECTL} create -f ../is-analytics/identity-server-analytics-1-service.yaml +${KUBECTL} create -f ../is-analytics/identity-server-analytics-2-service.yaml +${KUBECTL} create -f ../is-analytics/identity-server-analytics-service.yaml +sleep 10s + +# MySQL +echoBold 'Deploying WSO2 Identity Server and Identity Server Analytics Databases using MySQL...' +${KUBECTL} create -f ../extras/rdbms/mysql/mysql-deployment.yaml +sleep 10s + +# persistent storage +echoBold 'Creating persistent volume and volume claim...' +${KUBECTL} create -f ../is/identity-server-volume-claims.yaml +${KUBECTL} create -f ../is-analytics/identity-server-analytics-volume-claims.yaml +${KUBECTL} create -f ../volumes/persistent-volumes.yaml +sleep 10s + +# Identity Server and Analytics +echoBold 'Deploying WSO2 Identity Server and Analytics...' +${KUBECTL} create -f ../is/identity-server-deployment.yaml +${KUBECTL} create -f ../is-analytics/identity-server-analytics-1-deployment.yaml +${KUBECTL} create -f ../is-analytics/identity-server-analytics-2-deployment.yaml +sleep 30s + +echoBold 'Deploying Ingresses...' +${KUBECTL} create -f ../ingresses/identity-server-ingress.yaml +${KUBECTL} create -f ../ingresses/identity-server-analytics-ingress.yaml +sleep 30s + +echoBold 'Finished' +echo 'To access the WSO2 Identity Server management console, try https://wso2is/carbon in your browser.' +echo 'To access the WSO2 Identity Server Analytics management console, try https://wso2is-analytics/carbon in your browser.' diff --git a/is-with-analytics/scripts/undeploy.sh b/is-with-analytics/scripts/undeploy.sh new file mode 100755 index 00000000..86ad90f6 --- /dev/null +++ b/is-with-analytics/scripts/undeploy.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# ------------------------------------------------------------------------ +# Copyright 2018 WSO2, Inc. (http://wso2.com) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License +# ------------------------------------------------------------------------ + +set -e + +ECHO=`which echo` +KUBECTL=`which kubectl` + +# methods +function echoBold () { + echo $'\e[1m'"${1}"$'\e[0m' +} + +# persistent storage +echoBold 'Deleting persistent volume and volume claim...' +${KUBECTL} delete -f ../is/identity-server-volume-claims.yaml +${KUBECTL} delete -f ../volumes/persistent-volumes.yaml + +# WSO2 Identity Server +echoBold 'Deleting WSO2 Identity Server deployment...' +${KUBECTL} delete -f ../is/identity-server-service.yaml +${KUBECTL} delete -f ../is-analytics/identity-server-analytics-1-service.yaml +${KUBECTL} delete -f ../is-analytics/identity-server-analytics-2-service.yaml +${KUBECTL} delete -f ../is-analytics/identity-server-analytics-service.yaml +${KUBECTL} delete -f ../is/identity-server-deployment.yaml +${KUBECTL} delete -f ../is-analytics/identity-server-analytics-1-deployment.yaml +${KUBECTL} delete -f ../is-analytics/identity-server-analytics-2-deployment.yaml +sleep 2m + +# MySQL +echoBold 'Deleting the MySQL deployment...' +${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-service.yaml +${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-deployment.yaml +sleep 50s + +# delete the created Kubernetes Namespace +${KUBECTL} delete namespace wso2 + +# switch the context to default namespace +${KUBECTL} config set-context $(kubectl config current-context) --namespace=default + +echoBold 'Finished' diff --git a/is-with-analytics/test/deploy.sh b/is-with-analytics/test/deploy.sh deleted file mode 100755 index 1202832e..00000000 --- a/is-with-analytics/test/deploy.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash - -# ------------------------------------------------------------------------ -# Copyright 2018 WSO2, Inc. (http://wso2.com) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License -# ------------------------------------------------------------------------ - -# methods -set -e - -function echoBold () { - echo $'\e[1m'"${1}"$'\e[0m' -} - -# create a new Kubernetes Namespace -kubectl create namespace wso2 - -# create a new service account in 'wso2' Kubernetes Namespace -kubectl create serviceaccount wso2svc-account -n wso2 - -# switch the context to new 'wso2' namespace -kubectl config set-context $(kubectl config current-context) --namespace=wso2 - -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= - -# create Kubernetes role and role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme -kubectl create --username=admin --password= -f ../../rbac/rbac.yaml - -# configuration maps -echoBold 'Creating ConfigMaps...' -kubectl create configmap identity-server-conf --from-file=../confs/is/conf/ -kubectl create configmap identity-server-conf-axis2 --from-file=../confs/is/conf/axis2/ -kubectl create configmap identity-server-conf-datasources --from-file=../confs/is/conf/datasources/ -kubectl create configmap identity-server-conf-identity --from-file=../confs/is/conf/identity/ -kubectl create configmap identity-server-conf-event-publishers --from-file=../confs/is/deployment/server/eventpublishers/ - -kubectl create configmap is-analytics-1-conf --from-file=../confs/is-analytics-1/conf -kubectl create configmap is-analytics-1-conf-analytics --from-file=../confs/is-analytics-1/conf/analytics -kubectl create configmap is-analytics-1-conf-spark-analytics --from-file=../confs/is-analytics-1/conf/analytics/spark -kubectl create configmap is-analytics-1-conf-axis2 --from-file=../confs/is-analytics-1/conf/axis2 -kubectl create configmap is-analytics-1-conf-datasources --from-file=../confs/is-analytics-1/conf/datasources -kubectl create configmap is-analytics-1-deployment-portal --from-file=../confs/is-analytics-1/deployment/server/jaggeryapps/portal/configs - -kubectl create configmap is-analytics-2-conf --from-file=../confs/is-analytics-2/conf -kubectl create configmap is-analytics-2-conf-analytics --from-file=../confs/is-analytics-2/conf/analytics -kubectl create configmap is-analytics-2-conf-spark-analytics --from-file=../confs/is-analytics-2/conf/analytics/spark -kubectl create configmap is-analytics-2-conf-axis2 --from-file=../confs/is-analytics-2/conf/axis2 -kubectl create configmap is-analytics-2-conf-datasources --from-file=../confs/is-analytics-2/conf/datasources -kubectl create configmap is-analytics-2-deployment-portal --from-file=../confs/is-analytics-2/deployment/server/jaggeryapps/portal/configs - -kubectl create configmap mysql-dbscripts --from-file=confs/rdbms/mysql/dbscripts/ - -# MySQL -echoBold 'Deploying WSO2 Identity Server Databases...' -kubectl create -f rdbms/mysql/mysql-service.yaml -kubectl create -f rdbms/mysql/mysql-deployment.yaml -sleep 10s - -# persistent storage -echoBold 'Creating persistent volume and volume claim...' -kubectl create -f ../is/identity-server-volume-claims.yaml -kubectl create -f ../is-analytics/identity-server-analytics-volume-claims.yaml - -kubectl create -f ../volumes/persistent-volumes.yaml - -# Identity Server and Analytics -echoBold 'Deploying WSO2 Identity Server and Analytics...' -kubectl create -f ../is/identity-server-service.yaml -kubectl create -f ../is/identity-server-deployment.yaml -kubectl create -f ../is-analytics/identity-server-analytics-1-deployment.yaml -kubectl create -f ../is-analytics/identity-server-analytics-1-service.yaml -kubectl create -f ../is-analytics/identity-server-analytics-2-deployment.yaml -kubectl create -f ../is-analytics/identity-server-analytics-2-service.yaml -kubectl create -f ../is-analytics/identity-server-analytics-service.yaml -sleep 30s - -echoBold 'Deploying Ingresses...' -kubectl create -f ../ingresses/identity-server-ingress.yaml -kubectl create -f ../ingresses/identity-server-analytics-ingress.yaml -sleep 30s - -echoBold 'Finished' -echo 'To access the WSO2 Identity Server management console, try https://wso2is/carbon in your browser.' -echo 'To access the WSO2 Identity Server Analytics management console, try https://wso2is-analytics/carbon in your browser.' diff --git a/is-with-analytics/test/undeploy.sh b/is-with-analytics/test/undeploy.sh deleted file mode 100755 index d9bd5f3c..00000000 --- a/is-with-analytics/test/undeploy.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -# ------------------------------------------------------------------------ -# Copyright 2018 WSO2, Inc. (http://wso2.com) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License -# ------------------------------------------------------------------------ - -# methods -function echoBold () { - echo $'\e[1m'"${1}"$'\e[0m' -} - -# delete the created Kubernetes Namespace -kubectl delete namespace wso2 - -kubectl delete -f ../volumes/persistent-volumes.yaml - -sleep 50s - -# switch the context to default namespace -kubectl config set-context $(kubectl config current-context) --namespace=default - -echoBold 'Finished' diff --git a/is-with-analytics/volumes/persistent-volumes.yaml b/is-with-analytics/volumes/persistent-volumes.yaml index f7d0494a..92a6584b 100644 --- a/is-with-analytics/volumes/persistent-volumes.yaml +++ b/is-with-analytics/volumes/persistent-volumes.yaml @@ -57,7 +57,7 @@ metadata: node: wso2is-analytics-1 spec: capacity: - storage: 1Gi + storage: 20Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain @@ -74,6 +74,44 @@ metadata: labels: purpose: analytics-data node: wso2is-analytics-2 +spec: + capacity: + storage: 20Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + nfs: + server: + path: "" + +--- + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wso2is-with-analytics-is-analytics-pv-1 + labels: + purpose: analytics + node: wso2is-analytics-1 +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + nfs: + server: + path: "" + +--- + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wso2is-with-analytics-is-analytics-pv-2 + labels: + purpose: analytics + node: wso2is-analytics-2 spec: capacity: storage: 1Gi From 51cbc881c8d845a911003101cd5ca8a7a09ae1f9 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 16:25:26 +0530 Subject: [PATCH 03/24] Add shortened named argument support --- is-with-analytics/scripts/deploy.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/is-with-analytics/scripts/deploy.sh b/is-with-analytics/scripts/deploy.sh index d857899a..18e39b5c 100755 --- a/is-with-analytics/scripts/deploy.sh +++ b/is-with-analytics/scripts/deploy.sh @@ -30,9 +30,9 @@ function usage () { echoBold "This script automates the installation of WSO2 Identity Server pattern 1 Kubernetes resources\n" echoBold "Allowed arguments:\n" echoBold "-h | --help" - echoBold "--free-trial-username\t\tYour WSO2 Free Trial username" - echoBold "--free-trial-password\t\tYour WSO2 Free Trial password" - echoBold "--cluster-admin-password\tKubernetes cluster admin password\n\n" + echoBold "--ftu | --free-trial-username\t\tYour WSO2 Free Trial username" + echoBold "--ftp | --free-trial-password\t\tYour WSO2 Free Trial password" + echoBold "--cap | --cluster-admin-password\tKubernetes cluster admin password\n\n" } FT_USERNAME='' @@ -49,13 +49,13 @@ while [ "$1" != "" ]; do usage exit 1 ;; - --free-trial-username) + --ftu | --free-trial-username) FT_USERNAME=$VALUE ;; - --free-trial-password) + --ftp | --free-trial-password) FT_PASSWORD=$VALUE ;; - --cluster-admin-password) + --cap | --cluster-admin-password) ADMIN_PASSWORD=$VALUE ;; *) From 1d90aef9c91b27d3d1048ee35ee6cd628b2108af Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 17:13:11 +0530 Subject: [PATCH 04/24] Add support for persisting MySQL database data --- .../extras/rdbms/mysql/mysql-deployment.yaml | 8 +++++ .../mysql/mysql-persistent-volume-claim.yaml | 28 ++++++++++++++++++ .../rdbms/volumes/persistent-volumes.yaml | 29 +++++++++++++++++++ is-with-analytics/scripts/deploy.sh | 2 ++ is-with-analytics/scripts/undeploy.sh | 1 + 5 files changed, 68 insertions(+) create mode 100644 is-with-analytics/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml create mode 100644 is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml diff --git a/is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml b/is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml index 1ebbed86..a500cabc 100644 --- a/is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml +++ b/is-with-analytics/extras/rdbms/mysql/mysql-deployment.yaml @@ -27,6 +27,8 @@ spec: - name: wso2is-with-analytics-mysql image: mysql:5.7 imagePullPolicy: IfNotPresent + securityContext: + runAsUser: 999 env: - name: MYSQL_ROOT_PASSWORD value: root @@ -40,9 +42,15 @@ spec: volumeMounts: - name: mysql-dbscripts mountPath: /docker-entrypoint-initdb.d + - name: is-rdbms-persistent-storage + mountPath: /var/lib/mysql args: ["--max-connections", "10000"] volumes: - name: mysql-dbscripts configMap: name: mysql-dbscripts + - name: is-rdbms-persistent-storage + persistentVolumeClaim: + claimName: wso2is-with-analytics-rdbms-volume-claim + serviceAccountName: "wso2svc-account" \ No newline at end of file diff --git a/is-with-analytics/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml b/is-with-analytics/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml new file mode 100644 index 00000000..11f2883b --- /dev/null +++ b/is-with-analytics/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: wso2is-with-analytics-rdbms-volume-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + storageClassName: "" + selector: + matchLabels: + purpose: is-rdbms-data diff --git a/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml b/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml new file mode 100644 index 00000000..ab097390 --- /dev/null +++ b/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wso2is-with-analytics-mysql-pv + labels: + purpose: is-rdbms-data +spec: + capacity: + storage: 20Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: + path: "" diff --git a/is-with-analytics/scripts/deploy.sh b/is-with-analytics/scripts/deploy.sh index 18e39b5c..84351c81 100755 --- a/is-with-analytics/scripts/deploy.sh +++ b/is-with-analytics/scripts/deploy.sh @@ -123,7 +123,9 @@ sleep 10s echoBold 'Creating persistent volume and volume claim...' ${KUBECTL} create -f ../is/identity-server-volume-claims.yaml ${KUBECTL} create -f ../is-analytics/identity-server-analytics-volume-claims.yaml +${KUBECTL} create -f ../extras/rdbms/mysql/mysql-persistent-volume-claim.yaml ${KUBECTL} create -f ../volumes/persistent-volumes.yaml +${KUBECTL} create -f ../extras/rdbms/volumes/persistent-volumes.yaml sleep 10s # Identity Server and Analytics diff --git a/is-with-analytics/scripts/undeploy.sh b/is-with-analytics/scripts/undeploy.sh index 86ad90f6..1b98a53c 100755 --- a/is-with-analytics/scripts/undeploy.sh +++ b/is-with-analytics/scripts/undeploy.sh @@ -46,6 +46,7 @@ sleep 2m echoBold 'Deleting the MySQL deployment...' ${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-service.yaml ${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-deployment.yaml +${KUBECTL} delete -f ../extras/rdbms/volumes/persistent-volumes.yaml sleep 50s # delete the created Kubernetes Namespace From 99f4b9c6d9cde47f81d6c2590ee6182045dc340d Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 19:34:32 +0530 Subject: [PATCH 05/24] Add MySQL DB data persistence --- is/README.md | 14 +++++++++ is/extras/rdbms/mysql/mysql-deployment.yaml | 12 ++++++-- .../mysql/mysql-persistent-volume-claim.yaml | 28 +++++++++++++++++ .../rdbms/volumes/persistent-volumes.yaml | 29 ++++++++++++++++++ is/is.png | Bin 0 -> 38229 bytes is/{extras => scripts}/README.md | 5 +++ is/scripts/deploy.sh | 10 +++--- is/scripts/undeploy.sh | 2 ++ 8 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 is/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml create mode 100644 is/extras/rdbms/volumes/persistent-volumes.yaml create mode 100644 is/is.png rename is/{extras => scripts}/README.md (91%) diff --git a/is/README.md b/is/README.md index 6019e64e..9a56cbe4 100644 --- a/is/README.md +++ b/is/README.md @@ -2,6 +2,8 @@ Core Kubernetes resources for a clustered deployment of WSO2 Identity Server. +![A clustered deployment WSO2 Identity Server](is.png) + ## Prerequisites * In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) @@ -78,6 +80,18 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN ``` kubectl create configmap mysql-dbscripts --from-file=/is/extras/confs/mysql/dbscripts/ ``` + + Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. + Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. + Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource + named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. + + Then, deploy the persistent volume resource and volume claim as follows: + + ``` + kubectl create -f /is/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml + kubectl create -f /is/extras/rdbms/volumes/persistent-volumes.yaml + ``` Then, create a Kubernetes service (accessible only within the Kubernetes cluster) and followed by the MySQL Kubernetes deployment, as follows: diff --git a/is/extras/rdbms/mysql/mysql-deployment.yaml b/is/extras/rdbms/mysql/mysql-deployment.yaml index a6efa746..d5ed751a 100644 --- a/is/extras/rdbms/mysql/mysql-deployment.yaml +++ b/is/extras/rdbms/mysql/mysql-deployment.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,9 +24,11 @@ spec: deployment: wso2is-mysql spec: containers: - - name: wso2is-mysql + - name: wso2is-with-analytics-mysql image: mysql:5.7 imagePullPolicy: IfNotPresent + securityContext: + runAsUser: 999 env: - name: MYSQL_ROOT_PASSWORD value: root @@ -40,8 +42,14 @@ spec: volumeMounts: - name: mysql-dbscripts mountPath: /docker-entrypoint-initdb.d + - name: is-rdbms-persistent-storage + mountPath: /var/lib/mysql args: ["--max-connections", "10000"] volumes: - name: mysql-dbscripts configMap: name: mysql-dbscripts + - name: is-rdbms-persistent-storage + persistentVolumeClaim: + claimName: wso2is-rdbms-volume-claim + serviceAccountName: "wso2svc-account" diff --git a/is/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml b/is/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml new file mode 100644 index 00000000..011f6978 --- /dev/null +++ b/is/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: wso2is-rdbms-volume-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + storageClassName: "" + selector: + matchLabels: + purpose: is-rdbms-data diff --git a/is/extras/rdbms/volumes/persistent-volumes.yaml b/is/extras/rdbms/volumes/persistent-volumes.yaml new file mode 100644 index 00000000..7ba40480 --- /dev/null +++ b/is/extras/rdbms/volumes/persistent-volumes.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wso2is-mysql-pv + labels: + purpose: is-rdbms-data +spec: + capacity: + storage: 20Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: + path: "" diff --git a/is/is.png b/is/is.png new file mode 100644 index 0000000000000000000000000000000000000000..75d239965909fee303fdeabcee930672dabd23e4 GIT binary patch literal 38229 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 literal 0 HcmV?d00001 diff --git a/is/extras/README.md b/is/scripts/README.md similarity index 91% rename from is/extras/README.md rename to is/scripts/README.md index 1c0d4c29..13b8cdca 100644 --- a/is/extras/README.md +++ b/is/scripts/README.md @@ -47,6 +47,11 @@ Add `wso2carbon` user to the group `wso2`. Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. + +Finally, setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. +Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. +Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource +named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. ##### 4. Deploy Kubernetes resources: diff --git a/is/scripts/deploy.sh b/is/scripts/deploy.sh index 5f1509e9..a3d1e9bc 100755 --- a/is/scripts/deploy.sh +++ b/is/scripts/deploy.sh @@ -49,13 +49,13 @@ while [ "$1" != "" ]; do usage exit 1 ;; - --free-trial-username | --ftu) + --ftu | --free-trial-username) FT_USERNAME=$VALUE ;; - --free-trial-password | --ftp) + --ftp | --free-trial-password) FT_PASSWORD=$VALUE ;; - --cluster-admin-password | --cap) + --cap | --cluster-admin-password) ADMIN_PASSWORD=$VALUE ;; *) @@ -77,7 +77,7 @@ ${KUBECTL} create serviceaccount wso2svc-account -n wso2 ${KUBECTL} config set-context $(kubectl config current-context) --namespace=wso2 # create a Kubernetes Secret for passing WSO2 Private Docker Registry credentials -#${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} +${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} # create Kubernetes Role and Role Binding necessary for the Kubernetes API requests made from Kubernetes membership scheme ${KUBECTL} create --username=admin --password=${ADMIN_PASSWORD} -f ../../rbac/rbac.yaml @@ -104,6 +104,8 @@ sleep 10s echoBold 'Creating persistent volumes and volume claims...' ${KUBECTL} create -f ../identity-server-volume-claims.yaml ${KUBECTL} create -f ../volumes/persistent-volumes.yaml +${KUBECTL} create -f ../extras/rdbms/mysql/mysql-persistent-volume-claim.yaml +${KUBECTL} create -f ../extras/rdbms/volumes/persistent-volumes.yaml sleep 10s # WSO2 Identity Server diff --git a/is/scripts/undeploy.sh b/is/scripts/undeploy.sh index 6484face..4ebb861c 100755 --- a/is/scripts/undeploy.sh +++ b/is/scripts/undeploy.sh @@ -41,6 +41,8 @@ sleep 1m echoBold 'Deleting the MySQL deployment...' ${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-service.yaml ${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-deployment.yaml +${KUBECTL} delete -f ../extras/rdbms/mysql/mysql-persistent-volume-claim.yaml +${KUBECTL} delete -f ../extras/rdbms/volumes/persistent-volumes.yaml sleep 50s # delete the created Kubernetes Namespace From bc37b8f471bab8e8c875ec1f9a57988a80763dbe Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 19:44:38 +0530 Subject: [PATCH 06/24] Update README.md documentation --- is-with-analytics/README.md | 12 ++++++++++++ .../identity-server-analytics-1-deployment.yaml | 2 +- .../identity-server-analytics-2-deployment.yaml | 2 +- is-with-analytics/is/identity-server-deployment.yaml | 2 +- is-with-analytics/scripts/README.md | 5 +++++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index c8029407..10733bf6 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -84,6 +84,18 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN ``` kubectl create configmap mysql-dbscripts --from-file=/is-with-analytics/extras/confs/mysql/dbscripts/ ``` + + Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. + Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. + Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource + named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. + + Then, deploy the persistent volume resource and volume claim as follows: + + ``` + kubectl create -f /is-with-analytics/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml + kubectl create -f /is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml + ``` Then, create a Kubernetes service (accessible only within the Kubernetes cluster) and followed by the MySQL Kubernetes deployment, as follows: diff --git a/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml b/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml index ccca50a5..baf19437 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-1-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-1 - image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 + image: docker.wso2.com/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" diff --git a/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml b/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml index 7fab7f6d..2f1aea60 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-2-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-2 - image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 + image: docker.wso2.com/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" diff --git a/is-with-analytics/is/identity-server-deployment.yaml b/is-with-analytics/is/identity-server-deployment.yaml index addb8a90..eee606e3 100644 --- a/is-with-analytics/is/identity-server-deployment.yaml +++ b/is-with-analytics/is/identity-server-deployment.yaml @@ -31,7 +31,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is - image: gcr.io/apim3-177506/wso2is:5.6.0 + image: docker.wso2.com/wso2is:5.6.0 livenessProbe: exec: command: diff --git a/is-with-analytics/scripts/README.md b/is-with-analytics/scripts/README.md index 396027a0..b291b8df 100644 --- a/is-with-analytics/scripts/README.md +++ b/is-with-analytics/scripts/README.md @@ -52,6 +52,11 @@ Add `wso2carbon` user to the group `wso2`. Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +Finally, setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. +Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. +Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource +named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. + ##### 4. Deploy Kubernetes resources: Change directory to `KUBERNETES_HOME/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: From b4b4aebfce16ee6f45b8922ecc7135f8f7b6e214 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 23:14:05 +0530 Subject: [PATCH 07/24] Update the doc link --- is/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/is/README.md b/is/README.md index 9a56cbe4..300edfe7 100644 --- a/is/README.md +++ b/is/README.md @@ -56,7 +56,7 @@ for further details. ##### 4. Setup and configure external product database(s): -Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS550/Setting+Up+Separate+Databases+for+Clustering) +Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) on creating the required databases for the deployment. Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in From 3cd689462492ad50f48f36dfdd9b0758e6146465 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Fri, 22 Jun 2018 23:15:37 +0530 Subject: [PATCH 08/24] Update the doc link --- is-with-analytics/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index 10733bf6..8db6230c 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -56,7 +56,7 @@ for further details. ##### 4. Setup and configure external product database(s): -Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS550/Setting+Up+Separate+Databases+for+Clustering) +Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) on creating the required databases for the deployment. Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in From 53d867c59fb6847f00ca1ee9f4cd9ee5a487d11e Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Sun, 24 Jun 2018 19:20:38 +0530 Subject: [PATCH 09/24] Change the usage of the term free trial to WSO2 subscription --- is/README.md | 6 +++--- is/scripts/README.md | 6 +++--- is/scripts/deploy.sh | 28 ++++++++++++++-------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/is/README.md b/is/README.md index 300edfe7..538f93a5 100644 --- a/is/README.md +++ b/is/README.md @@ -45,11 +45,11 @@ kubectl config set-context $(kubectl config current-context) --namespace=wso2 Create a Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. ``` -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= +kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= ``` -`FT_USERNAME`: Username of your Free Trial Subscription
-`FT_PASSWORD`: Password of your Free Trial Subscription +`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
+`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. diff --git a/is/scripts/README.md b/is/scripts/README.md index 13b8cdca..cb7ce120 100644 --- a/is/scripts/README.md +++ b/is/scripts/README.md @@ -58,14 +58,14 @@ named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/p Change directory to `KUBERNETES_HOME/is/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh --free-trial-username= --free-trial-password= --cluster-admin-password= +./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= ``` * A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. The following details need to be replaced in the relevant command. -`FT_USERNAME`: Username of your Free Trial Subscription
-`FT_PASSWORD`: Password of your Free Trial Subscription +`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
+`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription * A Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. diff --git a/is/scripts/deploy.sh b/is/scripts/deploy.sh index a3d1e9bc..0c072f46 100755 --- a/is/scripts/deploy.sh +++ b/is/scripts/deploy.sh @@ -27,16 +27,16 @@ function echoBold () { } function usage () { - echoBold "This script automates the installation of WSO2 Identity Server pattern 1 Kubernetes resources\n" + echoBold "This script automates the installation of WSO2 EI Integrator Analytics Kubernetes resources\n" echoBold "Allowed arguments:\n" echoBold "-h | --help" - echoBold "--free-trial-username\t\tYour WSO2 Free Trial username" - echoBold "--free-trial-password\t\tYour WSO2 Free Trial password" - echoBold "--cluster-admin-password\tKubernetes cluster admin password\n\n" + echoBold "--wsu | --wso2-subscription-username\t\tYour WSO2 Subscription username" + echoBold "--wsp | --wso2-subscription-password\t\tYour WSO2 Subscription password" + echoBold "--cap | --cluster-admin-password\tKubernetes cluster admin password\n\n" } -FT_USERNAME='' -FT_PASSWORD='' +WSO2_SUBSCRIPTION_USERNAME='' +WSO2_SUBSCRIPTION_PASSWORD='' ADMIN_PASSWORD='' # capture named arguments @@ -44,22 +44,22 @@ while [ "$1" != "" ]; do PARAM=`echo $1 | awk -F= '{print $1}'` VALUE=`echo $1 | awk -F= '{print $2}'` - case $PARAM in + case ${PARAM} in -h | --help) usage exit 1 ;; - --ftu | --free-trial-username) - FT_USERNAME=$VALUE + --wsu | --wso2-subscription-username) + WSO2_SUBSCRIPTION_USERNAME=${VALUE} ;; - --ftp | --free-trial-password) - FT_PASSWORD=$VALUE + --wsp | --wso2-subscription-password) + WSO2_SUBSCRIPTION_PASSWORD=${VALUE} ;; --cap | --cluster-admin-password) - ADMIN_PASSWORD=$VALUE + ADMIN_PASSWORD=${VALUE} ;; *) - echoBold "ERROR: unknown parameter \"$PARAM\"" + echoBold "ERROR: unknown parameter \"${PARAM}\"" usage exit 1 ;; @@ -77,7 +77,7 @@ ${KUBECTL} create serviceaccount wso2svc-account -n wso2 ${KUBECTL} config set-context $(kubectl config current-context) --namespace=wso2 # create a Kubernetes Secret for passing WSO2 Private Docker Registry credentials -${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} +${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${WSO2_SUBSCRIPTION_USERNAME} --docker-password=${WSO2_SUBSCRIPTION_PASSWORD} --docker-email=${WSO2_SUBSCRIPTION_USERNAME} # create Kubernetes Role and Role Binding necessary for the Kubernetes API requests made from Kubernetes membership scheme ${KUBECTL} create --username=admin --password=${ADMIN_PASSWORD} -f ../../rbac/rbac.yaml From 82481c7a1d3d5a16a62b2f15febd62294406fbfe Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Sun, 24 Jun 2018 19:39:23 +0530 Subject: [PATCH 10/24] Change the usage of the term free trial to WSO2 subscription --- is-with-analytics/README.md | 6 +++--- is-with-analytics/scripts/README.md | 6 +++--- is-with-analytics/scripts/deploy.sh | 26 +++++++++++++------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index 8db6230c..59387134 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -45,11 +45,11 @@ kubectl config set-context $(kubectl config current-context) --namespace=wso2 Create a Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. ``` -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= +kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= ``` -`FT_USERNAME`: Username of your Free Trial Subscription
-`FT_PASSWORD`: Password of your Free Trial Subscription +`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
+`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. diff --git a/is-with-analytics/scripts/README.md b/is-with-analytics/scripts/README.md index b291b8df..bf04b2c7 100644 --- a/is-with-analytics/scripts/README.md +++ b/is-with-analytics/scripts/README.md @@ -62,14 +62,14 @@ named `wso2is-with-analytics-mysql-pv` in the file `/is-with-an Change directory to `KUBERNETES_HOME/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh --free-trial-username= --free-trial-password= --cluster-admin-password= +./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= ``` * A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. The following details need to be replaced in the relevant command. -`FT_USERNAME`: Username of your Free Trial Subscription
-`FT_PASSWORD`: Password of your Free Trial Subscription +`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
+`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription * A Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. diff --git a/is-with-analytics/scripts/deploy.sh b/is-with-analytics/scripts/deploy.sh index 84351c81..220ca162 100755 --- a/is-with-analytics/scripts/deploy.sh +++ b/is-with-analytics/scripts/deploy.sh @@ -27,16 +27,16 @@ function echoBold () { } function usage () { - echoBold "This script automates the installation of WSO2 Identity Server pattern 1 Kubernetes resources\n" + echoBold "This script automates the installation of WSO2 EI Integrator Analytics Kubernetes resources\n" echoBold "Allowed arguments:\n" echoBold "-h | --help" - echoBold "--ftu | --free-trial-username\t\tYour WSO2 Free Trial username" - echoBold "--ftp | --free-trial-password\t\tYour WSO2 Free Trial password" + echoBold "--wsu | --wso2-subscription-username\t\tYour WSO2 Subscription username" + echoBold "--wsp | --wso2-subscription-password\t\tYour WSO2 Subscription password" echoBold "--cap | --cluster-admin-password\tKubernetes cluster admin password\n\n" } -FT_USERNAME='' -FT_PASSWORD='' +WSO2_SUBSCRIPTION_USERNAME='' +WSO2_SUBSCRIPTION_PASSWORD='' ADMIN_PASSWORD='' # capture named arguments @@ -44,22 +44,22 @@ while [ "$1" != "" ]; do PARAM=`echo $1 | awk -F= '{print $1}'` VALUE=`echo $1 | awk -F= '{print $2}'` - case $PARAM in + case ${PARAM} in -h | --help) usage exit 1 ;; - --ftu | --free-trial-username) - FT_USERNAME=$VALUE + --wsu | --wso2-subscription-username) + WSO2_SUBSCRIPTION_USERNAME=${VALUE} ;; - --ftp | --free-trial-password) - FT_PASSWORD=$VALUE + --wsp | --wso2-subscription-password) + WSO2_SUBSCRIPTION_PASSWORD=${VALUE} ;; --cap | --cluster-admin-password) - ADMIN_PASSWORD=$VALUE + ADMIN_PASSWORD=${VALUE} ;; *) - echoBold "ERROR: unknown parameter \"$PARAM\"" + echoBold "ERROR: unknown parameter \"${PARAM}\"" usage exit 1 ;; @@ -77,7 +77,7 @@ ${KUBECTL} create serviceaccount wso2svc-account -n wso2 ${KUBECTL} config set-context $(${KUBECTL} config current-context) --namespace=wso2 # create a Kubernetes Secret for passing WSO2 Private Docker Registry credentials -${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${FT_USERNAME} --docker-password=${FT_PASSWORD} --docker-email=${FT_USERNAME} +${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${WSO2_SUBSCRIPTION_USERNAME} --docker-password=${WSO2_SUBSCRIPTION_PASSWORD} --docker-email=${WSO2_SUBSCRIPTION_USERNAME} # create Kubernetes Role and Role Binding necessary for the Kubernetes API requests made from Kubernetes membership scheme ${KUBECTL} create --username=admin --password=${ADMIN_PASSWORD} -f ../../rbac/rbac.yaml From 6b44df56078995ef0d907e841efea45bb21ebbea Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Sun, 24 Jun 2018 20:09:30 +0530 Subject: [PATCH 11/24] Add meaningful port names --- .../identity-server-analytics-1-service.yaml | 38 +++++++++---------- .../identity-server-analytics-2-service.yaml | 38 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/is-with-analytics/is-analytics/identity-server-analytics-1-service.yaml b/is-with-analytics/is-analytics/identity-server-analytics-1-service.yaml index 787b063d..0ea2b097 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-1-service.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-1-service.yaml @@ -29,78 +29,78 @@ spec: port: 7712 protocol: TCP - - name: 'spark-1' + name: 'spark-port-1' port: 11225 protocol: TCP - - name: 'spark-2' + name: 'spark-port-2' port: 10006 protocol: TCP - - name: 'spark-3' + name: 'spark-port-3' port: 11001 protocol: TCP - - name: 'spark-44' + name: 'spark-port-4' protocol: TCP port: 8082 - - name: 'spark-5' + name: 'spark-port-5' protocol: TCP port: 4041 - - name: 'spark6' + name: 'spark-port-6' protocol: TCP port: 12001 - - name: 'spark7' + name: 'spark-port-7' protocol: TCP port: 12002 - - name: 'spark8' + name: 'spark-port-8' protocol: TCP port: 12003 - - name: 'spark9' + name: 'spark-port-9' protocol: TCP port: 12004 - - name: 'spark10' + name: 'spark-port-10' protocol: TCP port: 12005 - - name: 'analytics1' + name: 'analytics-port-1' protocol: TCP port: 10007 - - name: 'analytics2' + name: 'analytics-port-2' protocol: TCP port: 11002 - - name: 'analytics3' + name: 'analytics-port-3' protocol: TCP port: 12501 - - name: 'analytics5' + name: 'analytics-port-4' protocol: TCP port: 13001 - - name: 'analytics6' + name: 'analytics-port-5' protocol: TCP port: 13501 - - name: 'analytics7' + name: 'analytics-port-6' protocol: TCP port: 14501 - - name: 'analytics8' + name: 'analytics-port-7' protocol: TCP port: 7078 - - name: 'analytics9' + name: 'analytics-port-8' protocol: TCP port: 6067 - - name: 'analytics10' + name: 'analytics-port-9' protocol: TCP port: 11003 diff --git a/is-with-analytics/is-analytics/identity-server-analytics-2-service.yaml b/is-with-analytics/is-analytics/identity-server-analytics-2-service.yaml index f1d66a08..bc02dfb3 100644 --- a/is-with-analytics/is-analytics/identity-server-analytics-2-service.yaml +++ b/is-with-analytics/is-analytics/identity-server-analytics-2-service.yaml @@ -29,78 +29,78 @@ spec: port: 7712 protocol: TCP - - name: 'spark-1' + name: 'spark-port-1' port: 11225 protocol: TCP - - name: 'spark-2' + name: 'spark-port-2' port: 10006 protocol: TCP - - name: 'spark-3' + name: 'spark-port-3' port: 11001 protocol: TCP - - name: 'spark-44' + name: 'spark-port-4' protocol: TCP port: 8082 - - name: 'spark-5' + name: 'spark-port-5' protocol: TCP port: 4041 - - name: 'spark6' + name: 'spark-port-6' protocol: TCP port: 12001 - - name: 'spark7' + name: 'spark-port-7' protocol: TCP port: 12002 - - name: 'spark8' + name: 'spark-port-8' protocol: TCP port: 12003 - - name: 'spark9' + name: 'spark-port-9' protocol: TCP port: 12004 - - name: 'spark10' + name: 'spark-port-10' protocol: TCP port: 12005 - - name: 'analytics1' + name: 'analytics-port-1' protocol: TCP port: 10007 - - name: 'analytics2' + name: 'analytics-port-2' protocol: TCP port: 11002 - - name: 'analytics3' + name: 'analytics-port-3' protocol: TCP port: 12501 - - name: 'analytics5' + name: 'analytics-port-4' protocol: TCP port: 13001 - - name: 'analytics6' + name: 'analytics-port-5' protocol: TCP port: 13501 - - name: 'analytics7' + name: 'analytics-port-6' protocol: TCP port: 14501 - - name: 'analytics8' + name: 'analytics-port-7' protocol: TCP port: 7078 - - name: 'analytics9' + name: 'analytics-port-8' protocol: TCP port: 6067 - - name: 'analytics10' + name: 'analytics-port-9' protocol: TCP port: 11003 From 93c5d0f3e7d096a5521e87e11c481ae090fe9853 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Mon, 25 Jun 2018 14:11:09 +0530 Subject: [PATCH 12/24] Update README.md documentation --- is/README.md | 5 ++--- is/scripts/README.md | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/is/README.md b/is/README.md index 538f93a5..09fcce57 100644 --- a/is/README.md +++ b/is/README.md @@ -6,9 +6,8 @@ Core Kubernetes resources for a clustered deployment of WSO2 Identity Server. ## Prerequisites -* In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server. -You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 +subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) (version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) diff --git a/is/scripts/README.md b/is/scripts/README.md index cb7ce120..63058e94 100644 --- a/is/scripts/README.md +++ b/is/scripts/README.md @@ -5,9 +5,8 @@ Kubernetes resources provided for a clustered deployment of WSO2 Identity Server ## Prerequisites -* In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server. -You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 +subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) (version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) From 0414b51a932ad70f2d60d8b4acb42f0e5fc5ebca Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Mon, 25 Jun 2018 14:13:10 +0530 Subject: [PATCH 13/24] Update README.md documentation --- is-with-analytics/README.md | 5 ++--- is-with-analytics/scripts/README.md | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index 59387134..94acdb9a 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -6,9 +6,8 @@ Core Kubernetes resources for a clustered deployment of WSO2 Identity Server wit ## Prerequisites -* In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server and -Identity Server Analytics. You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 +subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) (version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) diff --git a/is-with-analytics/scripts/README.md b/is-with-analytics/scripts/README.md index bf04b2c7..fb49a35a 100644 --- a/is-with-analytics/scripts/README.md +++ b/is-with-analytics/scripts/README.md @@ -5,9 +5,8 @@ Kubernetes resources provided for a clustered deployment of WSO2 Identity Server ## Prerequisites -* In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Identity Server and -Identity Server Analytics. You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 +subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) (version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) From 1f5560cdc3f84735c45a2da7dc992b73e68cda7f Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Mon, 25 Jun 2018 17:06:37 +0530 Subject: [PATCH 14/24] Adjust WSO2 credential terminology --- is-with-analytics/README.md | 6 +++--- is-with-analytics/scripts/README.md | 6 +++--- is-with-analytics/scripts/deploy.sh | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index 94acdb9a..a2a35efe 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -44,11 +44,11 @@ kubectl config set-context $(kubectl config current-context) --namespace=wso2 Create a Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. ``` -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= +kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= ``` -`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
-`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription +`WSO2_USERNAME`: Your WSO2 username
+`WSO2_PASSWORD`: Your WSO2 password Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. diff --git a/is-with-analytics/scripts/README.md b/is-with-analytics/scripts/README.md index fb49a35a..d5b09819 100644 --- a/is-with-analytics/scripts/README.md +++ b/is-with-analytics/scripts/README.md @@ -61,14 +61,14 @@ named `wso2is-with-analytics-mysql-pv` in the file `/is-with-an Change directory to `KUBERNETES_HOME/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= +./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= ``` * A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. The following details need to be replaced in the relevant command. -`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
-`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription +`WSO2_USERNAME`: Your WSO2 username
+`WSO2_PASSWORD`: Your WSO2 password * A Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. diff --git a/is-with-analytics/scripts/deploy.sh b/is-with-analytics/scripts/deploy.sh index 220ca162..91f4413c 100755 --- a/is-with-analytics/scripts/deploy.sh +++ b/is-with-analytics/scripts/deploy.sh @@ -27,11 +27,11 @@ function echoBold () { } function usage () { - echoBold "This script automates the installation of WSO2 EI Integrator Analytics Kubernetes resources\n" + echoBold "This script automates the installation of WSO2 Identity Server with Analytics Kubernetes resources\n" echoBold "Allowed arguments:\n" echoBold "-h | --help" - echoBold "--wsu | --wso2-subscription-username\t\tYour WSO2 Subscription username" - echoBold "--wsp | --wso2-subscription-password\t\tYour WSO2 Subscription password" + echoBold "--wu | --wso2-username\t\tYour WSO2 username" + echoBold "--wp | --wso2-password\t\tYour WSO2 password" echoBold "--cap | --cluster-admin-password\tKubernetes cluster admin password\n\n" } @@ -49,10 +49,10 @@ while [ "$1" != "" ]; do usage exit 1 ;; - --wsu | --wso2-subscription-username) + --wu | --wso2-username) WSO2_SUBSCRIPTION_USERNAME=${VALUE} ;; - --wsp | --wso2-subscription-password) + --wp | --wso2-password) WSO2_SUBSCRIPTION_PASSWORD=${VALUE} ;; --cap | --cluster-admin-password) From 50fbfcb5ea82dc841dc40d7c74b7086ee6b6793c Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Mon, 25 Jun 2018 17:22:57 +0530 Subject: [PATCH 15/24] Adjust WSO2 credential terminology --- is/README.md | 6 +++--- is/scripts/README.md | 6 +++--- is/scripts/deploy.sh | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/is/README.md b/is/README.md index 09fcce57..e1047682 100644 --- a/is/README.md +++ b/is/README.md @@ -44,11 +44,11 @@ kubectl config set-context $(kubectl config current-context) --namespace=wso2 Create a Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. ``` -kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= +kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username= --docker-password= --docker-email= ``` -`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
-`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription +`WSO2_USERNAME`: Your WSO2 username
+`WSO2_PASSWORD`: Your WSO2 password Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. diff --git a/is/scripts/README.md b/is/scripts/README.md index 63058e94..a1d45887 100644 --- a/is/scripts/README.md +++ b/is/scripts/README.md @@ -57,14 +57,14 @@ named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/p Change directory to `KUBERNETES_HOME/is/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= +./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= ``` * A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. The following details need to be replaced in the relevant command. -`WSO2_SUB_USERNAME`: Username of your WSO2 Subscription
-`WSO2_SUB_PASSWORD`: Password of your WSO2 Subscription +`WSO2_USERNAME`: Your WSO2 username
+`WSO2_PASSWORD`: Your WSO2 password * A Kubernetes role and a role binding necessary for the Kubernetes API requests made from Kubernetes membership scheme. diff --git a/is/scripts/deploy.sh b/is/scripts/deploy.sh index 0c072f46..0ee748e1 100755 --- a/is/scripts/deploy.sh +++ b/is/scripts/deploy.sh @@ -27,11 +27,11 @@ function echoBold () { } function usage () { - echoBold "This script automates the installation of WSO2 EI Integrator Analytics Kubernetes resources\n" + echoBold "This script automates the installation of WSO2 Identity Server Kubernetes resources\n" echoBold "Allowed arguments:\n" echoBold "-h | --help" - echoBold "--wsu | --wso2-subscription-username\t\tYour WSO2 Subscription username" - echoBold "--wsp | --wso2-subscription-password\t\tYour WSO2 Subscription password" + echoBold "--wu | --wso2-username\t\tYour WSO2 username" + echoBold "--wp | --wso2-password\t\tYour WSO2 password" echoBold "--cap | --cluster-admin-password\tKubernetes cluster admin password\n\n" } @@ -49,10 +49,10 @@ while [ "$1" != "" ]; do usage exit 1 ;; - --wsu | --wso2-subscription-username) + --wu | --wso2-username) WSO2_SUBSCRIPTION_USERNAME=${VALUE} ;; - --wsp | --wso2-subscription-password) + --wp | --wso2-password) WSO2_SUBSCRIPTION_PASSWORD=${VALUE} ;; --cap | --cluster-admin-password) @@ -74,7 +74,7 @@ ${KUBECTL} create namespace wso2 ${KUBECTL} create serviceaccount wso2svc-account -n wso2 # switch the context to new 'wso2' namespace -${KUBECTL} config set-context $(kubectl config current-context) --namespace=wso2 +${KUBECTL} config set-context $(${KUBECTL} config current-context) --namespace=wso2 # create a Kubernetes Secret for passing WSO2 Private Docker Registry credentials ${KUBECTL} create secret docker-registry wso2creds --docker-server=docker.wso2.com --docker-username=${WSO2_SUBSCRIPTION_USERNAME} --docker-password=${WSO2_SUBSCRIPTION_PASSWORD} --docker-email=${WSO2_SUBSCRIPTION_USERNAME} From c09672bec73fbabe3f12271dba2d3b0684e6978c Mon Sep 17 00:00:00 2001 From: ThilinaManamgoda Date: Sun, 1 Jul 2018 08:48:58 +0530 Subject: [PATCH 16/24] Add Helm resources for IS-5.6.0 --- helm/is/README.md | 5 +- helm/is/is-conf/confs/bin/wso2server.sh | 318 ------------------ .../confs/repository/conf/axis2/axis2.xml | 4 +- .../is-conf/confs/repository/conf/carbon.xml | 2 +- .../repository/conf/identity/identity.xml | 58 +++- helm/is/is-conf/templates/is-conf-bin.yaml | 30 -- .../is-conf/templates/persistent-volumes.yaml | 4 +- helm/is/is-conf/values.yaml | 12 +- .../templates/identity-server-deployment.yaml | 6 +- 9 files changed, 71 insertions(+), 368 deletions(-) delete mode 100644 helm/is/is-conf/confs/bin/wso2server.sh delete mode 100644 helm/is/is-conf/templates/is-conf-bin.yaml diff --git a/helm/is/README.md b/helm/is/README.md index f01fdc3b..4a6522b3 100644 --- a/helm/is/README.md +++ b/helm/is/README.md @@ -2,9 +2,8 @@ ## Prerequisites -* In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Enterprise Identity Server. -You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Helm resources, you need an active WSO2 subscription. If you do not possess an active WSO2 + subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Helm](https://github.com/kubernetes/helm/blob/master/docs/install.md) (and Tiller) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) in order to run the diff --git a/helm/is/is-conf/confs/bin/wso2server.sh b/helm/is/is-conf/confs/bin/wso2server.sh deleted file mode 100644 index a69d70d1..00000000 --- a/helm/is/is-conf/confs/bin/wso2server.sh +++ /dev/null @@ -1,318 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Copyright 2018 WSO2, Inc. http://www.wso2.org -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# ---------------------------------------------------------------------------- -# Main Script for the WSO2 Carbon Server -# -# Environment Variable Prequisites -# -# CARBON_HOME Home of WSO2 Carbon installation. If not set I will try -# to figure it out. -# -# JAVA_HOME Must point at your Java Development Kit installation. -# -# JAVA_OPTS (Optional) Java runtime options used when the commands -# is executed. -# -# NOTE: Borrowed generously from Apache Tomcat startup scripts. -# ----------------------------------------------------------------------------- - -# OS specific support. $var _must_ be set to either true or false. -#ulimit -n 100000 - -cygwin=false; -darwin=false; -os400=false; -mingw=false; -case "`uname`" in -CYGWIN*) cygwin=true;; -MINGW*) mingw=true;; -OS400*) os400=true;; -Darwin*) darwin=true - if [ -z "$JAVA_VERSION" ] ; then - JAVA_VERSION="CurrentJDK" - else - echo "Using Java version: $JAVA_VERSION" - fi - if [ -z "$JAVA_HOME" ] ; then - JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home - fi - ;; -esac - -# resolve links - $0 may be a softlink -PRG="$0" - -while [ -h "$PRG" ]; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '.*/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`/"$link" - fi -done - -# Get standard environment variables -PRGDIR=`dirname "$PRG"` - -# Only set CARBON_HOME if not already set -[ -z "$CARBON_HOME" ] && CARBON_HOME=`cd "$PRGDIR/.." ; pwd` - -# Set AXIS2_HOME. Needed for One Click JAR Download -AXIS2_HOME="$CARBON_HOME" - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CARBON_HOME" ] && CARBON_HOME=`cygpath --unix "$CARBON_HOME"` - [ -n "$AXIS2_HOME" ] && CARBON_HOME=`cygpath --unix "$CARBON_HOME"` -fi - -# For OS400 -if $os400; then - # Set job priority to standard for interactive (interactive - 6) by using - # the interactive priority - 6, the helper threads that respond to requests - # will be running at the same priority as interactive jobs. - COMMAND='chgjob job('$JOBNAME') runpty(6)' - system $COMMAND - - # Enable multi threading - QIBM_MULTI_THREADED=Y - export QIBM_MULTI_THREADED -fi - -# For Migwn, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$CARBON_HOME" ] && - CARBON_HOME="`(cd "$CARBON_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - [ -n "$AXIS2_HOME" ] && - CARBON_HOME="`(cd "$CARBON_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD=java - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." - echo " CARBON cannot execute $JAVACMD" - exit 1 -fi - -# if JAVA_HOME is not set we're not happy -if [ -z "$JAVA_HOME" ]; then - echo "You must set the JAVA_HOME variable before running CARBON." - exit 1 -fi - -if [ -e "$CARBON_HOME/wso2carbon.pid" ]; then - PID=`cat "$CARBON_HOME"/wso2carbon.pid` -fi - -# ----- Process the input command ---------------------------------------------- -args="" -for c in $* -do - if [ "$c" = "--debug" ] || [ "$c" = "-debug" ] || [ "$c" = "debug" ]; then - CMD="--debug" - continue - elif [ "$CMD" = "--debug" ]; then - if [ -z "$PORT" ]; then - PORT=$c - fi - elif [ "$c" = "--stop" ] || [ "$c" = "-stop" ] || [ "$c" = "stop" ]; then - CMD="stop" - elif [ "$c" = "--start" ] || [ "$c" = "-start" ] || [ "$c" = "start" ]; then - CMD="start" - elif [ "$c" = "--version" ] || [ "$c" = "-version" ] || [ "$c" = "version" ]; then - CMD="version" - elif [ "$c" = "--restart" ] || [ "$c" = "-restart" ] || [ "$c" = "restart" ]; then - CMD="restart" - elif [ "$c" = "--test" ] || [ "$c" = "-test" ] || [ "$c" = "test" ]; then - CMD="test" - else - args="$args $c" - fi -done - -if [ "$CMD" = "--debug" ]; then - if [ "$PORT" = "" ]; then - echo " Please specify the debug port after the --debug option" - exit 1 - fi - if [ -n "$JAVA_OPTS" ]; then - echo "Warning !!!. User specified JAVA_OPTS will be ignored, once you give the --debug option." - fi - CMD="RUN" - JAVA_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=$PORT" - echo "Please start the remote debugging client to continue..." -elif [ "$CMD" = "start" ]; then - if [ -e "$CARBON_HOME/wso2carbon.pid" ]; then - if ps -p $PID > /dev/null ; then - echo "Process is already running" - exit 0 - fi - fi - export CARBON_HOME="$CARBON_HOME" -# using nohup sh to avoid erros in solaris OS.TODO - nohup sh "$CARBON_HOME"/bin/wso2server.sh $args > /dev/null 2>&1 & - exit 0 -elif [ "$CMD" = "stop" ]; then - export CARBON_HOME="$CARBON_HOME" - kill -term `cat "$CARBON_HOME"/wso2carbon.pid` - exit 0 -elif [ "$CMD" = "restart" ]; then - export CARBON_HOME="$CARBON_HOME" - kill -term `cat "$CARBON_HOME"/wso2carbon.pid` - process_status=0 - pid=`cat "$CARBON_HOME"/wso2carbon.pid` - while [ "$process_status" -eq "0" ] - do - sleep 1; - ps -p$pid 2>&1 > /dev/null - process_status=$? - done - -# using nohup sh to avoid erros in solaris OS.TODO - nohup sh "$CARBON_HOME"/bin/wso2server.sh $args > /dev/null 2>&1 & - exit 0 -elif [ "$CMD" = "test" ]; then - JAVACMD="exec "$JAVACMD"" -elif [ "$CMD" = "version" ]; then - cat "$CARBON_HOME"/bin/version.txt - cat "$CARBON_HOME"/bin/wso2carbon-version.txt - exit 0 -fi - -# ---------- Handle the SSL Issue with proper JDK version -------------------- -jdk_17=`$JAVA_HOME/bin/java -version 2>&1 | grep "1.[7|8]"` -if [ "$jdk_17" = "" ]; then - echo " Starting WSO2 Carbon (in unsupported JDK)" - echo " [ERROR] CARBON is supported only on JDK 1.7 and 1.8" -fi - -CARBON_XBOOTCLASSPATH="" -for f in "$CARBON_HOME"/lib/xboot/*.jar -do - if [ "$f" != "$CARBON_HOME/lib/xboot/*.jar" ];then - CARBON_XBOOTCLASSPATH="$CARBON_XBOOTCLASSPATH":$f - fi -done - -JAVA_ENDORSED_DIRS="$CARBON_HOME/lib/endorsed":"$JAVA_HOME/jre/lib/endorsed":"$JAVA_HOME/lib/endorsed" - -CARBON_CLASSPATH="" -if [ -e "$JAVA_HOME/lib/tools.jar" ]; then - CARBON_CLASSPATH="$JAVA_HOME/lib/tools.jar" -fi -for f in "$CARBON_HOME"/bin/*.jar -do - if [ "$f" != "$CARBON_HOME/bin/*.jar" ];then - CARBON_CLASSPATH="$CARBON_CLASSPATH":$f - fi -done -for t in "$CARBON_HOME"/lib/commons-lang*.jar -do - CARBON_CLASSPATH="$CARBON_CLASSPATH":$t -done -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - JAVA_HOME=`cygpath --absolute --windows "$JAVA_HOME"` - CARBON_HOME=`cygpath --absolute --windows "$CARBON_HOME"` - AXIS2_HOME=`cygpath --absolute --windows "$CARBON_HOME"` - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"` - CARBON_CLASSPATH=`cygpath --path --windows "$CARBON_CLASSPATH"` - CARBON_XBOOTCLASSPATH=`cygpath --path --windows "$CARBON_XBOOTCLASSPATH"` -fi - -# ----- Execute The Requested Command ----------------------------------------- - -echo JAVA_HOME environment variable is set to $JAVA_HOME -echo CARBON_HOME environment variable is set to "$CARBON_HOME" - -cd "$CARBON_HOME" - -TMP_DIR="$CARBON_HOME"/tmp -if [ -d "$TMP_DIR" ]; then -rm -rf "$TMP_DIR"/* -fi - -START_EXIT_STATUS=121 -status=$START_EXIT_STATUS - -if [ -z "$JVM_MEM_OPTS" ]; then - java_version=$("$JAVACMD" -version 2>&1 | awk -F '"' '/version/ {print $2}') - JVM_MEM_OPTS="-Xms256m -Xmx1024m" - if [ "$java_version" \< "1.8" ]; then - JVM_MEM_OPTS="$JVM_MEM_OPTS -XX:MaxPermSize=256m" - fi -fi -echo "Using Java memory options: $JVM_MEM_OPTS" - -#To monitor a Carbon server in remote JMX mode on linux host machines, set the below system property. -# -Djava.rmi.server.hostname="your.IP.goes.here" - -while [ "$status" = "$START_EXIT_STATUS" ] -do - $JAVACMD \ - -Xbootclasspath/a:"$CARBON_XBOOTCLASSPATH" \ - $JVM_MEM_OPTS \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:HeapDumpPath="$CARBON_HOME/repository/logs/heap-dump.hprof" \ - $JAVA_OPTS \ - -Dcom.sun.management.jmxremote \ - -classpath "$CARBON_CLASSPATH" \ - -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \ - -Djava.io.tmpdir="$CARBON_HOME/tmp" \ - -Dcatalina.base="$CARBON_HOME/lib/tomcat" \ - -Dwso2.server.standalone=true \ - -Dcarbon.registry.root=/ \ - -Djava.command="$JAVACMD" \ - -Dcarbon.home="$CARBON_HOME" \ - -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \ - -Dcarbon.config.dir.path="$CARBON_HOME/repository/conf" \ - -Djava.util.logging.config.file="$CARBON_HOME/repository/conf/etc/logging-bridge.properties" \ - -Dcomponents.repo="$CARBON_HOME/repository/components/plugins" \ - -Dconf.location="$CARBON_HOME/repository/conf"\ - -Dcom.atomikos.icatch.file="$CARBON_HOME/lib/transactions.properties" \ - -Dcom.atomikos.icatch.hide_init_file_path=true \ - -Dorg.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false \ - -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true \ - -Dcom.sun.jndi.ldap.connect.pool.authentication=simple \ - -Dcom.sun.jndi.ldap.connect.pool.timeout=3000 \ - -Dorg.terracotta.quartz.skipUpdateCheck=true \ - -Djava.security.egd=file:/dev/./urandom \ - -Dfile.encoding=UTF8 \ - -Djava.net.preferIPv4Stack=true \ - -Dcom.ibm.cacheLocalHost=true \ - -DworkerNode=false \ - org.wso2.carbon.bootstrap.Bootstrap $* - status=$? -done diff --git a/helm/is/is-conf/confs/repository/conf/axis2/axis2.xml b/helm/is/is-conf/confs/repository/conf/axis2/axis2.xml index 60db6c66..ee761786 100644 --- a/helm/is/is-conf/confs/repository/conf/axis2/axis2.xml +++ b/helm/is/is-conf/confs/repository/conf/axis2/axis2.xml @@ -73,10 +73,10 @@ axis2modules - WSO2 Identity Server-5.5.0 + WSO2 Identity Server-5.6.0 - WSO2 Identity Server-5.5.0 + WSO2 Identity Server-5.6.0 diff --git a/helm/is/is-conf/confs/repository/conf/carbon.xml b/helm/is/is-conf/confs/repository/conf/carbon.xml index 4b6abd0f..1b35fb7b 100644 --- a/helm/is/is-conf/confs/repository/conf/carbon.xml +++ b/helm/is/is-conf/confs/repository/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 + true + + 20 + + 40 + @@ -189,6 +199,12 @@ true org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor + + false false @@ -603,13 +619,14 @@ + - + orderId="90" enable="false"/> + orderId="93" enable="true"/> @@ -634,6 +651,21 @@ + + + + + + + + + 300 + + + true + + 1000 + 1000 + 51200 + + + + + + http://localhost:8280/ + + 5 + + diff --git a/helm/is/is-conf/templates/is-conf-bin.yaml b/helm/is/is-conf/templates/is-conf-bin.yaml deleted file mode 100644 index d8b69920..00000000 --- a/helm/is/is-conf/templates/is-conf-bin.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -apiVersion: v1 -kind: ConfigMap -metadata: - name: is-conf-bin - namespace : {{ .Values.namespace }} -data: - {{- $file := .Files }} - {{- range $path, $byte := .Files.Glob "confs/bin/*" }} - {{- $list := $path | splitList "/"}} - {{- $length := len $list }} - {{- $last := add $length -1 }} - {{ index $list $last }}: |- - {{- range $file.Lines $path }} - {{ . }} - {{- end }} - {{- end }} diff --git a/helm/is/is-conf/templates/persistent-volumes.yaml b/helm/is/is-conf/templates/persistent-volumes.yaml index bad9bc49..e60a5c0b 100644 --- a/helm/is/is-conf/templates/persistent-volumes.yaml +++ b/helm/is/is-conf/templates/persistent-volumes.yaml @@ -15,7 +15,7 @@ apiVersion: v1 kind: PersistentVolume metadata: - name: wso2is-with-analytics-shared-deployment-pv + name: wso2is-shared-deployment-pv namespace : {{ .Values.namespace }} labels: purpose: is-shared-deployment @@ -34,7 +34,7 @@ spec: apiVersion: v1 kind: PersistentVolume metadata: - name: wso2is-with-analytics-shared-tenants-pv + name: wso2is-shared-tenants-pv namespace : {{ .Values.namespace }} labels: purpose: is-shared-tenants diff --git a/helm/is/is-conf/values.yaml b/helm/is/is-conf/values.yaml index f8bb84ad..052df9ed 100644 --- a/helm/is/is-conf/values.yaml +++ b/helm/is/is-conf/values.yaml @@ -1,9 +1,9 @@ -username: "" -password: "" -email: "" +username: "thilinama@wso2.com" +password: "" +email: "thilinama@wso2.com" namespace: "wso2" svcaccount: "wso2svc-account" -serverIp: "" -sharedDeploymentLocationPath: "" -sharedTentsLocationPath: "" +serverIp: "10.128.0.6" +sharedDeploymentLocationPath: "/data/is/deployment" +sharedTentsLocationPath: "/data/is/tenants" diff --git a/helm/is/is-deployment/templates/identity-server-deployment.yaml b/helm/is/is-deployment/templates/identity-server-deployment.yaml index e81e051d..ad733e53 100644 --- a/helm/is/is-deployment/templates/identity-server-deployment.yaml +++ b/helm/is/is-deployment/templates/identity-server-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is - image: docker.wso2.com/wso2is:5.5.0 + image: gcr.io/apim3-177506/wso2is:5.6.0 livenessProbe: exec: command: @@ -65,9 +65,9 @@ spec: - name: identity-server-conf-identity mountPath: /home/wso2carbon/kubernetes-volumes/is/conf-identity - name: shared-deployment-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/deployment + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/deployment - name: shared-tenants-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/tenants + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/tenants serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds From c6c37931b72a978772398f5cb16a640ec5fe530a Mon Sep 17 00:00:00 2001 From: ThilinaManamgoda Date: Sun, 1 Jul 2018 12:00:37 +0530 Subject: [PATCH 17/24] Add Helm resources for Is-with-Analytics-deployment --- helm/is-with-analytics/README.md | 14 ++--- .../confs/is-analytics-1/conf/axis2/axis2.xml | 4 +- .../confs/is-analytics-1/conf/carbon.xml | 2 +- .../confs/is-analytics-2/conf/axis2/axis2.xml | 4 +- .../confs/is-analytics-2/conf/carbon.xml | 2 +- .../confs/is/conf/axis2/axis2.xml | 4 +- .../confs/is/conf/carbon.xml | 2 +- .../confs/is/conf/identity/identity.xml | 58 ++++++++++++++++++- ...Analytics-Publisher-wso2event-RoleData.xml | 41 +++++++++---- ...Analytics-Publisher-wso2event-UserData.xml | 41 +++++++++---- .../templates/_helpers.tpl | 6 +- .../templates/persistent-volumes.yaml | 44 +++++++++++++- .../is-with-analytics-conf/values.yaml | 13 +++-- .../templates/_helpers.tpl | 6 +- ...dentity-server-analytics-1-deployment.yaml | 9 ++- .../identity-server-analytics-1-service.yaml | 38 ++++++------ ...dentity-server-analytics-2-deployment.yaml | 9 ++- .../identity-server-analytics-2-service.yaml | 38 ++++++------ ...entity-server-analytics-volume-claims.yaml | 42 +++++++++++++- .../templates/identity-server-deployment.yaml | 6 +- helm/is/README.md | 2 +- helm/is/is-conf/values.yaml | 12 ++-- .../templates/identity-server-deployment.yaml | 2 +- 23 files changed, 290 insertions(+), 109 deletions(-) diff --git a/helm/is-with-analytics/README.md b/helm/is-with-analytics/README.md index 1dcfd4b2..2c633fa2 100644 --- a/helm/is-with-analytics/README.md +++ b/helm/is-with-analytics/README.md @@ -1,10 +1,8 @@ # Helm Charts for deployment of WSO2 Identity Server with Analytics ## Prerequisites - -* In order to use these Kubernetes resources, you will need an active [Free Trial Subscription](https://wso2.com/free-trial-subscription) -from WSO2 since the referring Docker images hosted at docker.wso2.com contains the latest updates and fixes for WSO2 Enterprise Identity Server. -You can sign up for a Free Trial Subscription [here](https://wso2.com/free-trial-subscription).

+In order to use WSO2 Helm resources, you need an active WSO2 subscription. If you do not possess an active WSO2 + subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Helm](https://github.com/kubernetes/helm/blob/master/docs/install.md) (and Tiller) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) in order to run the @@ -44,8 +42,10 @@ configurations as necessary. `sharedDeploymentLocationPath`: NFS shared deployment directory(/repository/deployment) location for IS
`sharedTentsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS
`analytics1DataLocationPath`: NFS volume for Indexed data for Analytics node 1(/repository/data)
- `analytics2DataLocationPath`: NFS volume for Indexed data for Analytics node 2(/repository/data) - + `analytics2DataLocationPath`: NFS volume for Indexed data for Analytics node 2(/repository/data)
+ `analytics1LocationPath`: NFS volume for Analytics data for Analytics node 1(/repository/analytics)
+ `analytics2LocationPath`: NFS volume for Analytics data for Analytics node 2(/repository/analytics) + 3. Open the `/is-with-analytics-deployment/values.yaml` and provide the following values. `namespace`: Namespace
@@ -80,7 +80,7 @@ Default deployment will expose two publicly accessible hosts, namely:
To access the console in a test environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing`). +1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing -n wso2`). e.g. diff --git a/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/axis2/axis2.xml b/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/axis2/axis2.xml index 00b9b349..670d4c38 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/axis2/axis2.xml +++ b/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/axis2/axis2.xml @@ -73,10 +73,10 @@ axis2modules - WSO2 Identity Server Analytics-5.5.0 + WSO2 Identity Server Analytics-5.6.0 - WSO2 Identity Server Analytics-5.5.0 + WSO2 Identity Server Analytics-5.6.0 diff --git a/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/carbon.xml b/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/carbon.xml index 79ff505f..50bb5910 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/carbon.xml +++ b/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-1/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 diff --git a/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-2/conf/carbon.xml b/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-2/conf/carbon.xml index 79ff505f..50bb5910 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-2/conf/carbon.xml +++ b/helm/is-with-analytics/is-with-analytics-conf/confs/is-analytics-2/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 diff --git a/helm/is-with-analytics/is-with-analytics-conf/confs/is/conf/carbon.xml b/helm/is-with-analytics/is-with-analytics-conf/confs/is/conf/carbon.xml index 4b6abd0f..1b35fb7b 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/confs/is/conf/carbon.xml +++ b/helm/is-with-analytics/is-with-analytics-conf/confs/is/conf/carbon.xml @@ -36,7 +36,7 @@ - 5.5.0 + 5.6.0 + true + + 20 + + 40 + @@ -189,6 +199,12 @@ true org.wso2.carbon.identity.oauth.tokenprocessor.PlainTextPersistenceProcessor + + false false @@ -603,13 +619,14 @@ + - + orderId="90" enable="false"/> + orderId="93" enable="true"/> @@ -634,6 +651,21 @@ + + + + + + + + + 300 + + + true + + 1000 + 1000 + 51200 + + + + + + http://localhost:8280/ + + 5 + + diff --git a/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml b/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml index 1ed4d0c2..29c9cc95 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml +++ b/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-RoleData.xml @@ -1,13 +1,32 @@ - - - - - admin - thrift - non-blocking - 0 - tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 - admin - + + + + + + + admin + thrift + non-blocking + 0 + tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 + admin + diff --git a/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml b/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml index 2b9b97ac..a6021d71 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml +++ b/helm/is-with-analytics/is-with-analytics-conf/confs/is/deployment/server/eventpublishers/IsAnalytics-Publisher-wso2event-UserData.xml @@ -1,13 +1,32 @@ - - - - - admin - thrift - non-blocking - 0 - tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 - admin - + + + + + + + admin + thrift + non-blocking + 0 + tcp://wso2is-with-analytics-is-analytics-1-service:7612,tcp://wso2is-with-analytics-is-analytics-2-service:7612 + admin + diff --git a/helm/is-with-analytics/is-with-analytics-conf/templates/_helpers.tpl b/helm/is-with-analytics/is-with-analytics-conf/templates/_helpers.tpl index cb84135c..082cbce5 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/templates/_helpers.tpl +++ b/helm/is-with-analytics/is-with-analytics-conf/templates/_helpers.tpl @@ -15,7 +15,7 @@ limitations under the License. {{/* Expand the name of the chart. */}} -{{- define "scalable-is-with-analytics-conf.name" -}} +{{- define "is-with-analytics-conf.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} @@ -24,7 +24,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "scalable-is-with-analytics-conf.fullname" -}} +{{- define "is-with-analytics-conf.fullname" -}} {{- if .Values.fullnameOverride -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} @@ -40,6 +40,6 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "scalable-is-with-analytics-conf.chart" -}} +{{- define "is-with-analytics-conf.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- end -}} diff --git a/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml b/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml index 99bb48ae..be9b6ba2 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml +++ b/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml @@ -60,7 +60,7 @@ metadata: node: wso2is-analytics-1 spec: capacity: - storage: 1Gi + storage: 20Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain @@ -80,10 +80,50 @@ metadata: node: wso2is-analytics-2 spec: capacity: - storage: 1Gi + storage: 20Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: server: {{ .Values.serverIp }} path: {{ .Values.analytics2DataLocationPath }} + +--- + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wso2is-with-analytics-is-analytics-pv-1 + namespace : {{ .Values.namespace }} + labels: + purpose: analytics + node: wso2is-analytics-1 +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + nfs: + server: {{ .Values.serverIp }} + path: {{ .Values.analytics1LocationPath }} + +--- + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: wso2is-with-analytics-is-analytics-pv-2 + namespace : {{ .Values.namespace }} + labels: + purpose: analytics + node: wso2is-analytics-2 +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + nfs: + server: {{ .Values.serverIp }} + path: {{ .Values.analytics2LocationPath }} diff --git a/helm/is-with-analytics/is-with-analytics-conf/values.yaml b/helm/is-with-analytics/is-with-analytics-conf/values.yaml index 0151dd5b..b4b873ec 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/values.yaml +++ b/helm/is-with-analytics/is-with-analytics-conf/values.yaml @@ -4,9 +4,12 @@ email: "" namespace: "wso2" svcaccount: "wso2svc-account" -serverIp: "" -sharedDeploymentLocationPath: "" -sharedTentsLocationPath: "" -analytics1DataLocationPath: "" -analytics2DataLocationPath: "" +serverIp: "SERVER_IP" +sharedDeploymentLocationPath: "" +sharedTentsLocationPath: "" +analytics1DataLocationPath: "" +analytics2DataLocationPath: "" +analytics1LocationPath: "" +analytics2LocationPath: "" + diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/_helpers.tpl b/helm/is-with-analytics/is-with-analytics-deployment/templates/_helpers.tpl index 62d99ad5..9e78340f 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/_helpers.tpl +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/_helpers.tpl @@ -2,7 +2,7 @@ {{/* Expand the name of the chart. */}} -{{- define "scalable-is-with-analytics-deployment.name" -}} +{{- define "is-with-analytics-deployment.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} @@ -11,7 +11,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "scalable-is-with-analytics-deployment.fullname" -}} +{{- define "is-with-analytics-deployment.fullname" -}} {{- if .Values.fullnameOverride -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} @@ -27,6 +27,6 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "scalable-is-with-analytics-deployment.chart" -}} +{{- define "is-with-analytics-deployment.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- end -}} diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml index bac0073d..d397d3ea 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml @@ -33,7 +33,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-1 - image: docker.wso2.com/wso2is-analytics:5.5.0 + image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" @@ -127,8 +127,10 @@ spec: mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-datasources - name: is-analytics-1-deployment-portal mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-portal + - name: analytics-persistent-disk + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/conf/analytics - name: data-persistent-disk - mountPath: /home/wso2carbon/wso2is-analytics-5.5.0/repository/data + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/data serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds @@ -151,6 +153,9 @@ spec: - name: is-analytics-1-deployment-portal configMap: name: is-analytics-1-deployment-portal + - name: analytics-persistent-disk + persistentVolumeClaim: + claimName: is-analytics-1-analytics-volume-claim - name: data-persistent-disk persistentVolumeClaim: claimName: is-analytics-1-data-volume-claim diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-service.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-service.yaml index 7117d364..bf991a82 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-service.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-service.yaml @@ -30,78 +30,78 @@ spec: port: 7712 protocol: TCP - - name: 'spark-1' + name: 'spark-port-1' port: 11225 protocol: TCP - - name: 'spark-2' + name: 'spark-port-2' port: 10006 protocol: TCP - - name: 'spark-3' + name: 'spark-port-3' port: 11001 protocol: TCP - - name: 'spark-44' + name: 'spark-port-4' protocol: TCP port: 8082 - - name: 'spark-5' + name: 'spark-port-5' protocol: TCP port: 4041 - - name: 'spark6' + name: 'spark-port-6' protocol: TCP port: 12001 - - name: 'spark7' + name: 'spark-port-7' protocol: TCP port: 12002 - - name: 'spark8' + name: 'spark-port-8' protocol: TCP port: 12003 - - name: 'spark9' + name: 'spark-port-9' protocol: TCP port: 12004 - - name: 'spark10' + name: 'spark-port-10' protocol: TCP port: 12005 - - name: 'analytics1' + name: 'analytics-port-1' protocol: TCP port: 10007 - - name: 'analytics2' + name: 'analytics-port-2' protocol: TCP port: 11002 - - name: 'analytics3' + name: 'analytics-port-3' protocol: TCP port: 12501 - - name: 'analytics5' + name: 'analytics-port-4' protocol: TCP port: 13001 - - name: 'analytics6' + name: 'analytics-port-5' protocol: TCP port: 13501 - - name: 'analytics7' + name: 'analytics-port-6' protocol: TCP port: 14501 - - name: 'analytics8' + name: 'analytics-port-7' protocol: TCP port: 7078 - - name: 'analytics9' + name: 'analytics-port-8' protocol: TCP port: 6067 - - name: 'analytics10' + name: 'analytics-port-9' protocol: TCP port: 11003 diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml index a5bbab41..9c1e70bb 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml @@ -33,7 +33,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-2 - image: docker.wso2.com/wso2is-analytics:5.5.0 + image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" @@ -127,8 +127,10 @@ spec: mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-datasources - name: is-analytics-2-deployment-portal mountPath: /home/wso2carbon/kubernetes-volumes/is-analytics/conf-portal + - name: analytics-persistent-disk + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/conf/analytics - name: data-persistent-disk - mountPath: /home/wso2carbon/wso2is-analytics-5.5.0/repository/data + mountPath: /home/wso2carbon/wso2is-analytics-5.6.0/repository/data serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds @@ -151,6 +153,9 @@ spec: - name: is-analytics-2-deployment-portal configMap: name: is-analytics-2-deployment-portal + - name: analytics-persistent-disk + persistentVolumeClaim: + claimName: is-analytics-2-analytics-volume-claim - name: data-persistent-disk persistentVolumeClaim: claimName: is-analytics-2-data-volume-claim diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-service.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-service.yaml index 9547000f..eec447f9 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-service.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-service.yaml @@ -30,78 +30,78 @@ spec: port: 7712 protocol: TCP - - name: 'spark-1' + name: 'spark-port-1' port: 11225 protocol: TCP - - name: 'spark-2' + name: 'spark-port-2' port: 10006 protocol: TCP - - name: 'spark-3' + name: 'spark-port-3' port: 11001 protocol: TCP - - name: 'spark-44' + name: 'spark-port-4' protocol: TCP port: 8082 - - name: 'spark-5' + name: 'spark-port-5' protocol: TCP port: 4041 - - name: 'spark6' + name: 'spark-port-6' protocol: TCP port: 12001 - - name: 'spark7' + name: 'spark-port-7' protocol: TCP port: 12002 - - name: 'spark8' + name: 'spark-port-8' protocol: TCP port: 12003 - - name: 'spark9' + name: 'spark-port-9' protocol: TCP port: 12004 - - name: 'spark10' + name: 'spark-port-10' protocol: TCP port: 12005 - - name: 'analytics1' + name: 'analytics-port-1' protocol: TCP port: 10007 - - name: 'analytics2' + name: 'analytics-port-2' protocol: TCP port: 11002 - - name: 'analytics3' + name: 'analytics-port-3' protocol: TCP port: 12501 - - name: 'analytics5' + name: 'analytics-port-4' protocol: TCP port: 13001 - - name: 'analytics6' + name: 'analytics-port-5' protocol: TCP port: 13501 - - name: 'analytics7' + name: 'analytics-port-6' protocol: TCP port: 14501 - - name: 'analytics8' + name: 'analytics-port-7' protocol: TCP port: 7078 - - name: 'analytics9' + name: 'analytics-port-8' protocol: TCP port: 6067 - - name: 'analytics10' + name: 'analytics-port-9' protocol: TCP port: 11003 diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-volume-claims.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-volume-claims.yaml index d4df5615..8d45ac6f 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-volume-claims.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-volume-claims.yaml @@ -22,7 +22,7 @@ spec: - ReadWriteMany resources: requests: - storage: 1Gi + storage: 20Gi storageClassName: "" selector: matchLabels: @@ -41,9 +41,47 @@ spec: - ReadWriteMany resources: requests: - storage: 1Gi + storage: 20Gi storageClassName: "" selector: matchLabels: purpose: analytics-data node: wso2is-analytics-2 + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: is-analytics-1-analytics-volume-claim + namespace : {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: "" + selector: + matchLabels: + purpose: analytics + node: wso2is-analytics-1 + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: is-analytics-2-analytics-volume-claim + namespace : {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: "" + selector: + matchLabels: + purpose: analytics + node: wso2is-analytics-2 diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml index 90310eb7..68f850a0 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is - image: docker.wso2.com/wso2is:5.5.0 + image: gcr.io/apim3-177506/wso2is:5.6.0 livenessProbe: exec: command: @@ -67,9 +67,9 @@ spec: - name: identity-server-conf-event-publishers mountPath: /home/wso2carbon/kubernetes-volumes/is/conf-event-publishers - name: shared-deployment-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/deployment + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/deployment - name: shared-tenants-persistent-disk - mountPath: /home/wso2carbon/wso2is-5.5.0/repository/tenants + mountPath: /home/wso2carbon/wso2is-5.6.0/repository/tenants serviceAccountName: "wso2svc-account" imagePullSecrets: - name: wso2creds diff --git a/helm/is/README.md b/helm/is/README.md index 4a6522b3..6d2fd4a9 100644 --- a/helm/is/README.md +++ b/helm/is/README.md @@ -75,7 +75,7 @@ Default deployment will expose following publicly accessible host, namely:
To access the console in a test environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing`). +1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing -n wso2`). e.g. diff --git a/helm/is/is-conf/values.yaml b/helm/is/is-conf/values.yaml index 052df9ed..dfd2efd4 100644 --- a/helm/is/is-conf/values.yaml +++ b/helm/is/is-conf/values.yaml @@ -1,9 +1,9 @@ -username: "thilinama@wso2.com" -password: "" -email: "thilinama@wso2.com" +username: "" +password: "" +email: "" namespace: "wso2" svcaccount: "wso2svc-account" -serverIp: "10.128.0.6" -sharedDeploymentLocationPath: "/data/is/deployment" -sharedTentsLocationPath: "/data/is/tenants" +serverIp: "" +sharedDeploymentLocationPath: "" +sharedTentsLocationPath: "" \ No newline at end of file diff --git a/helm/is/is-deployment/templates/identity-server-deployment.yaml b/helm/is/is-deployment/templates/identity-server-deployment.yaml index ad733e53..5e55f388 100644 --- a/helm/is/is-deployment/templates/identity-server-deployment.yaml +++ b/helm/is/is-deployment/templates/identity-server-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is - image: gcr.io/apim3-177506/wso2is:5.6.0 + image: docker.wso2.com/wso2is:5.6.0 livenessProbe: exec: command: From 8cac63fda7fbbe2d2d859b934b7fbe55438c9e0e Mon Sep 17 00:00:00 2001 From: ThilinaManamgoda Date: Sun, 1 Jul 2018 12:03:50 +0530 Subject: [PATCH 18/24] Set docker registry domain --- .../templates/identity-server-analytics-1-deployment.yaml | 2 +- .../templates/identity-server-analytics-2-deployment.yaml | 2 +- .../templates/identity-server-deployment.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml index d397d3ea..6a89d075 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-1-deployment.yaml @@ -33,7 +33,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-1 - image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 + image: docker.wso2.com/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml index 9c1e70bb..3a0d3624 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-analytics-2-deployment.yaml @@ -33,7 +33,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is-analytics-2 - image: gcr.io/apim3-177506/wso2is-analytics:5.6.0 + image: docker.wso2.com/wso2is-analytics:5.6.0 resources: limits: memory: "4Gi" diff --git a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml index 68f850a0..f4fe19ee 100644 --- a/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml +++ b/helm/is-with-analytics/is-with-analytics-deployment/templates/identity-server-deployment.yaml @@ -32,7 +32,7 @@ spec: spec: containers: - name: wso2is-with-analytics-is - image: gcr.io/apim3-177506/wso2is:5.6.0 + image: docker.wso2.com/wso2is:5.6.0 livenessProbe: exec: command: From 43bf8c37148d97692938e0f738d5906cb21969f1 Mon Sep 17 00:00:00 2001 From: ThilinaManamgoda Date: Sun, 1 Jul 2018 12:09:16 +0530 Subject: [PATCH 19/24] Fix typos --- helm/is-with-analytics/is-with-analytics-conf/values.yaml | 2 +- helm/is/is-conf/values.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/helm/is-with-analytics/is-with-analytics-conf/values.yaml b/helm/is-with-analytics/is-with-analytics-conf/values.yaml index b4b873ec..c4197aa3 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/values.yaml +++ b/helm/is-with-analytics/is-with-analytics-conf/values.yaml @@ -4,7 +4,7 @@ email: "" namespace: "wso2" svcaccount: "wso2svc-account" -serverIp: "SERVER_IP" +serverIp: "" sharedDeploymentLocationPath: "" sharedTentsLocationPath: "" analytics1DataLocationPath: "" diff --git a/helm/is/is-conf/values.yaml b/helm/is/is-conf/values.yaml index dfd2efd4..f8bb84ad 100644 --- a/helm/is/is-conf/values.yaml +++ b/helm/is/is-conf/values.yaml @@ -6,4 +6,4 @@ namespace: "wso2" svcaccount: "wso2svc-account" serverIp: "" sharedDeploymentLocationPath: "" -sharedTentsLocationPath: "" \ No newline at end of file +sharedTentsLocationPath: "" From 333282c10447782b1ead43b3f808ead98073f999 Mon Sep 17 00:00:00 2001 From: ThilinaManamgoda Date: Sun, 1 Jul 2018 13:15:18 +0530 Subject: [PATCH 20/24] Fix typos --- helm/is-with-analytics/README.md | 2 +- .../is-with-analytics-conf/templates/persistent-volumes.yaml | 2 +- helm/is-with-analytics/is-with-analytics-conf/values.yaml | 2 +- helm/is/README.md | 2 +- helm/is/is-conf/templates/persistent-volumes.yaml | 2 +- helm/is/is-conf/values.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/helm/is-with-analytics/README.md b/helm/is-with-analytics/README.md index 2c633fa2..6f9be184 100644 --- a/helm/is-with-analytics/README.md +++ b/helm/is-with-analytics/README.md @@ -40,7 +40,7 @@ configurations as necessary. `serverIp`: NFS Server IP
`locationPath`: NFS location path
`sharedDeploymentLocationPath`: NFS shared deployment directory(/repository/deployment) location for IS
- `sharedTentsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS
+ `sharedTenantsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS
`analytics1DataLocationPath`: NFS volume for Indexed data for Analytics node 1(/repository/data)
`analytics2DataLocationPath`: NFS volume for Indexed data for Analytics node 2(/repository/data)
`analytics1LocationPath`: NFS volume for Analytics data for Analytics node 1(/repository/analytics)
diff --git a/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml b/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml index be9b6ba2..10f6f0fb 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml +++ b/helm/is-with-analytics/is-with-analytics-conf/templates/persistent-volumes.yaml @@ -46,7 +46,7 @@ spec: persistentVolumeReclaimPolicy: Retain nfs: server: {{ .Values.serverIp }} - path: {{ .Values.sharedTentsLocationPath }} + path: {{ .Values.sharedTenantsLocationPath }} --- diff --git a/helm/is-with-analytics/is-with-analytics-conf/values.yaml b/helm/is-with-analytics/is-with-analytics-conf/values.yaml index c4197aa3..db903290 100644 --- a/helm/is-with-analytics/is-with-analytics-conf/values.yaml +++ b/helm/is-with-analytics/is-with-analytics-conf/values.yaml @@ -6,7 +6,7 @@ namespace: "wso2" svcaccount: "wso2svc-account" serverIp: "" sharedDeploymentLocationPath: "" -sharedTentsLocationPath: "" +sharedTenantsLocationPath: "" analytics1DataLocationPath: "" analytics2DataLocationPath: "" analytics1LocationPath: "" diff --git a/helm/is/README.md b/helm/is/README.md index 6d2fd4a9..6f4c20e3 100644 --- a/helm/is/README.md +++ b/helm/is/README.md @@ -40,7 +40,7 @@ configurations as necessary. `svcaccount`: Service Account
`serverIp`: NFS Server IP
`sharedDeploymentLocationPath`: NFS shared deployment directory(/repository/deployment) location for IS
- `sharedTentsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS + `sharedTenantsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS 3. Open the `/is-deployment/values.yaml` and provide the following values. diff --git a/helm/is/is-conf/templates/persistent-volumes.yaml b/helm/is/is-conf/templates/persistent-volumes.yaml index e60a5c0b..2c6018a4 100644 --- a/helm/is/is-conf/templates/persistent-volumes.yaml +++ b/helm/is/is-conf/templates/persistent-volumes.yaml @@ -46,4 +46,4 @@ spec: persistentVolumeReclaimPolicy: Retain nfs: server: {{ .Values.serverIp }} - path: {{ .Values.sharedTentsLocationPath }} \ No newline at end of file + path: {{ .Values.sharedTenantsLocationPath }} \ No newline at end of file diff --git a/helm/is/is-conf/values.yaml b/helm/is/is-conf/values.yaml index f8bb84ad..687a3094 100644 --- a/helm/is/is-conf/values.yaml +++ b/helm/is/is-conf/values.yaml @@ -6,4 +6,4 @@ namespace: "wso2" svcaccount: "wso2svc-account" serverIp: "" sharedDeploymentLocationPath: "" -sharedTentsLocationPath: "" +sharedTenantsLocationPath: "" From 28be6cdad3852e72c5056af12a6073a8ba9cd079 Mon Sep 17 00:00:00 2001 From: ThilinaManamgoda Date: Mon, 2 Jul 2018 13:42:36 +0530 Subject: [PATCH 21/24] Fix typo --- helm/is-with-analytics/README.md | 2 +- helm/is/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/helm/is-with-analytics/README.md b/helm/is-with-analytics/README.md index 6f9be184..56d9f9a9 100644 --- a/helm/is-with-analytics/README.md +++ b/helm/is-with-analytics/README.md @@ -57,7 +57,7 @@ configurations as necessary. helm install --name /is-with-analytics-conf ``` -##### 4. Deploy MySql: +##### 4. Deploy MySQL: If there is an external product database(s), add those configurations as stated at `step 2.1`. Otherwise, run the below command to create the product database. ``` diff --git a/helm/is/README.md b/helm/is/README.md index 6f4c20e3..26620066 100644 --- a/helm/is/README.md +++ b/helm/is/README.md @@ -53,7 +53,7 @@ configurations as necessary. helm install --name /is-conf ``` -##### 4. Deploy MySql: +##### 4. Deploy MySQL: If there is an external product database(s), add those configurations as stated at `step 2.1`. Otherwise, run the below command to create the product database. ``` From 8ed755660ec196c3ff76d8d55573f77ae6e6fe92 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Mon, 2 Jul 2018 17:28:37 +0530 Subject: [PATCH 22/24] Upgrade README.md documentation --- is-with-analytics/README.md | 27 ++++++++---- is-with-analytics/scripts/README.md | 68 ++++++++++++++++++++++------- is/README.md | 27 ++++++++---- is/scripts/README.md | 62 +++++++++++++++++++------- 4 files changed, 135 insertions(+), 49 deletions(-) diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index a2a35efe..9a61801e 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -20,7 +20,7 @@ in order to run the steps provided
in the following quick start guide.

In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Checkout Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: ``` git clone https://github.com/wso2/kubernetes-is.git @@ -53,7 +53,7 @@ kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. -##### 4. Setup and configure external product database(s): +##### 4. Setup product database(s): Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) on creating the required databases for the deployment. @@ -85,7 +85,7 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN ``` Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. - Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. + Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. @@ -113,7 +113,8 @@ kubectl create --username=admin --password= -f /is-with-analytics/volumes/persistent-volumes.yaml` file. * `wso2is-with-analytics-shared-deployment-pv` * `wso2is-with-analytics-shared-tenants-pv` @@ -122,13 +123,21 @@ Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) * `wso2is-with-analytics-is-analytics-pv-1` * `wso2is-with-analytics-is-analytics-pv-2` -in `/is-with-analytics/volumes/persistent-volumes.yaml` file. - -Create a user named `wso2carbon` with user id `802` and a group named `wso2` with group id `802` in the NFS node. +Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. Add `wso2carbon` user to the group `wso2`. -Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` + +Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. +And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. + +``` +sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH +chmod -R 700 NFS_LOCATION_PATH +``` Then, deploy the persistent volume resource and volume claim as follows: diff --git a/is-with-analytics/scripts/README.md b/is-with-analytics/scripts/README.md index d5b09819..8c97dfe4 100644 --- a/is-with-analytics/scripts/README.md +++ b/is-with-analytics/scripts/README.md @@ -19,7 +19,7 @@ in order to run the steps provided
in the following quick start guide.

In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Checkout Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: ``` git clone https://github.com/wso2/kubernetes-is.git @@ -34,7 +34,8 @@ please refer the official documentation, [NGINX Ingress Controller Installation ##### 3. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. -Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resources, +Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of the following persistent volume resources +defined in the `/is-with-analytics/volumes/persistent-volumes.yaml` file. * `wso2is-with-analytics-shared-deployment-pv` * `wso2is-with-analytics-shared-tenants-pv` @@ -43,25 +44,60 @@ Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) * `wso2is-with-analytics-is-analytics-data-pv-1` * `wso2is-with-analytics-is-analytics-data-pv-2` -in `/is-with-analytics/volumes/persistent-volumes.yaml` file. - -Create a user named `wso2carbon` with user id `802` and a group named `wso2` with group id `802` in the NFS node. +Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. Add `wso2carbon` user to the group `wso2`. -Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` + +Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. +And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. + +``` +sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH +chmod -R 700 NFS_LOCATION_PATH +``` + +##### 4. Setup product database(s): + +For **evaluation purposes**, + +* You can use Kubernetes resources provided in the directory `KUBERNETES_HOME/is-with-analytics/extras/rdbms/mysql` +for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is +**not recommended** for a production setup. + +* For using these Kubernetes resources, + + Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. + Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. + Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource + named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. + +In a **production grade setup**, -Finally, setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. -Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. -Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource -named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. +* Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) + on creating the required databases for the deployment. + + Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in + the following files: + + * `KUBERNETES_HOME/is-with-analytics/confs/is/datasources/master-datasources.xml` + * `KUBERNETES_HOME/is-with-analytics/confs/is/datasources/bps-datasources.xml` + * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-1/datasources/master-datasources.xml` + * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-1/datasources/analytics-datasources.xml` + * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-2/datasources/master-datasources.xml` + * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-2/datasources/analytics-datasources.xml` + + Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN44x/Configuring+master-datasources.xml) on configuring data sources. -##### 4. Deploy Kubernetes resources: +##### 5. Deploy Kubernetes resources: Change directory to `KUBERNETES_HOME/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= +./deploy.sh --wso2-username= --wso2-password= --cluster-admin-password= ``` * A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. @@ -76,7 +112,7 @@ The following details need to be replaced in the relevant command. >To un-deploy, be on the same directory and execute the `undeploy.sh` shell script on the terminal. -##### 5. Access Management Consoles: +##### 6. Access Management Consoles: Default deployment will expose `wso2is` and `wso2is-analytics` hosts (to expose Administrative services and Management Console). @@ -101,13 +137,13 @@ wso2is-with-analytics-is-ingress wso2is 3. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. -##### 6. Scale up using `kubectl scale`: +##### 7. Scale up using `kubectl scale`: Default deployment runs two replicas (or pods) of WSO2 Identity server. To scale this deployment into any `` number of container replicas, upon your requirement, simply run following Kubernetes client command on the terminal. ``` -kubectl scale --replicas= -f /is/identity-server-deployment.yaml +kubectl scale --replicas= -f /is-with-analytics/is/identity-server-deployment.yaml ``` For example, If `` is 2, you are here scaling up this deployment from 1 to 2 container replicas. diff --git a/is/README.md b/is/README.md index e1047682..a58616cc 100644 --- a/is/README.md +++ b/is/README.md @@ -20,7 +20,7 @@ in order to run the steps provided
in the following quick start guide.

In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Checkout Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: ``` git clone https://github.com/wso2/kubernetes-is.git @@ -53,7 +53,7 @@ kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. -##### 4. Setup and configure external product database(s): +##### 4. Setup product database(s): Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) on creating the required databases for the deployment. @@ -81,7 +81,7 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN ``` Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. - Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. + Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. @@ -109,18 +109,27 @@ kubectl create --username=admin --password= -f /is/volumes/persistent-volumes.yaml` file. * `wso2is-shared-deployment-pv` * `wso2is-shared-tenants-pv` -in `/is/volumes/persistent-volumes.yaml` file. - -Create a user named `wso2carbon` with user id `802` and a group named `wso2` with group id `802` in the NFS node. +Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. Add `wso2carbon` user to the group `wso2`. -Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` + +Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. +And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. + +``` +sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH +chmod -R 700 NFS_LOCATION_PATH +``` Then, deploy the persistent volume resource and volume claim as follows: diff --git a/is/scripts/README.md b/is/scripts/README.md index a1d45887..03ccd375 100644 --- a/is/scripts/README.md +++ b/is/scripts/README.md @@ -19,7 +19,7 @@ in order to run the steps provided
in the following quick start guide.

In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Checkout Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: ``` git clone https://github.com/wso2/kubernetes-is.git @@ -34,30 +34,62 @@ please refer the official documentation, [NGINX Ingress Controller Installation ##### 3. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. -Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resources, +Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of the following persistent volume resources +defined in the `/is/volumes/persistent-volumes.yaml` file. * `wso2is-shared-deployment-pv` * `wso2is-shared-tenants-pv` -in `/is/volumes/persistent-volumes.yaml` file. - -Create a user named `wso2carbon` with user id `802` and a group named `wso2` with group id `802` in the NFS node. +Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. Add `wso2carbon` user to the group `wso2`. -Then, provide ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And provide read-write-executable permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` + +Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. +And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. + +``` +sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH +chmod -R 700 NFS_LOCATION_PATH +``` + +##### 4. Setup product database(s): -Finally, setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. -Provide read-write-executable permissions to `other` users, for the folder `NFS_LOCATION_PATH`. -Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource -named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. +For **evaluation purposes**, + +* You can use Kubernetes resources provided in the directory `KUBERNETES_HOME/is/extras/rdbms/mysql` +for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is +**not recommended** for a production setup. + +* For using these Kubernetes resources, + + Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. + Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. + Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource + named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. + +In a **production grade setup**, + +* Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) + on creating the required databases for the deployment. + + Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in + the following files: + + * `KUBERNETES_HOME/is/confs/is/datasources/master-datasources.xml` + * `KUBERNETES_HOME/is/confs/is/datasources/bps-datasources.xml` + + Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN44x/Configuring+master-datasources.xml) on configuring data sources. -##### 4. Deploy Kubernetes resources: +##### 5. Deploy Kubernetes resources: Change directory to `KUBERNETES_HOME/is/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` -./deploy.sh --wso2-subscription-username= --wso2-subscription-password= --cluster-admin-password= +./deploy.sh --wso2-username= --wso2-password= --cluster-admin-password= ``` * A Kubernetes Secret named `wso2creds` in the cluster to authenticate with the [`WSO2 Docker Registry`](https://docker.wso2.com), to pull the required images. @@ -72,7 +104,7 @@ The following details need to be replaced in the relevant command. >To un-deploy, be on the same directory and execute the `undeploy.sh` shell script on the terminal. -##### 5. Access Management Console: +##### 6. Access Management Console: Default deployment will expose `wso2is` host (to expose Administrative services and Management Console). @@ -95,7 +127,7 @@ wso2is-ingress wso2is 80, 443 3m 3. Try navigating to `https://wso2is/carbon` from your favorite browser. -##### 6. Scale up using `kubectl scale`: +##### 7. Scale up using `kubectl scale`: Default deployment runs a single replica (or pod) of WSO2 Identity server. To scale this deployment into any `` number of container replicas, upon your requirement, simply run following Kubernetes client command on the terminal. From f51a41909bfa3b256b34bb1ed0d49703c50256b1 Mon Sep 17 00:00:00 2001 From: chirangaalwis Date: Tue, 10 Jul 2018 12:34:36 +0530 Subject: [PATCH 23/24] Update README.md documentation --- README.md | 126 ++++++++++++++++++++++++-- helm/is-with-analytics/README.md | 132 ++++++++++++++++++---------- helm/is/README.md | 107 ++++++++++++++-------- is-with-analytics/README.md | 110 ++++++++++++----------- is-with-analytics/scripts/README.md | 102 +++++++++++---------- is/README.md | 87 ++++++++++-------- is/scripts/README.md | 90 +++++++++++-------- 7 files changed, 496 insertions(+), 258 deletions(-) diff --git a/README.md b/README.md index 150ff10b..bbc6690e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,123 @@ -# Kubernetes Resources for WSO2 Identity Server -*Kubernetes Resources for container-based deployments of WSO2 Identity Server* +# Kubernetes and Helm Resources for WSO2 Identity Server +*Kubernetes and Helm Resources for container-based deployments of WSO2 Identity Server deployment patterns* -This repository contains Kubernetes resources required for, -* [A clustered deployment of WSO2 Identity Server](is) +This repository contains Kubernetes and Helm resources required for, -* [A clustered deployment of WSO2 Identity Server with Analytics support](is-with-analytics) +* A clustered deployment of WSO2 Identity Server + +* A clustered deployment of WSO2 Identity Server with Analytics support + +## Deploy Kubernetes resources + +In order to deploy Kubernetes resources for each deployment pattern, follow the **Quick Start Guide**s for each deployment pattern +given below: + +* [A clustered deployment of WSO2 Identity Server](is/README.md) + +* [A clustered deployment of WSO2 Identity Server with Analytics support](is-with-analytics/README.md) + +## Deploy Helm resources + +In order to deploy Helm resources for each deployment pattern, follow the **Quick Start Guide**s for each deployment pattern +given below: + +* [A clustered deployment of WSO2 Identity Server](helm/is/README.md) + +* [A clustered deployment of WSO2 Identity Server with Analytics support](helm/is-with-analytics/README.md) + +## How to update configurations + +Kubernetes resources for WSO2 products use Kubernetes [ConfigMaps](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) +to pass on the minimum set of configurations required to setup a product deployment pattern. + +For example, the minimum set of configurations required to setup a clustered deployment of WSO2 Identity Server can be found +in `/is/confs` directory. The Kubernetes ConfigMaps are generated from these files. + +If you intend to pass on any additional files with configuration changes, third-party libraries, OSGi bundles and security +related artifacts to the Kubernetes cluster, you may mount the desired content to `/home/wso2carbon/wso2-server-volume` directory path within +a WSO2 product Docker container. + +The following example depicts how this can be achieved when passing additional configurations to WSO2 Identity Server +in a clustered deployment of WSO2 Identity Server: + +a. In order to apply the updated configurations, WSO2 product server instances need to be restarted. Hence, un-deploy all the Kubernetes resources +corresponding to the product deployment, if they are already deployed. + +b. Create and export a directory within the NFS server instance. + +c. Add the additional configuration files, third-party libraries, OSGi bundles and security related artifacts, into appropriate +folders matching that of the relevant WSO2 product home folder structure, within the previously created directory. + +d. Grant ownership to `wso2carbon` user and `wso2` group, for the directory created in step (b). + + ``` + sudo chown -R wso2carbon:wso2 + ``` + +e. Grant read-write-execute permissions to the `wso2carbon` user, for the directory created in step (b). + + ``` + chmod -R 700 + ``` + +f. Map the directory created in step (b) to a Kubernetes [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) +in the `/is/volumes/persistent-volumes.yaml` file. For example, append the following entry to the file: + +``` +apiVersion: v1 +kind: PersistentVolume +metadata: + name: identity-server-additional-config-pv + labels: + purpose: is-additional-configs +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + nfs: + server: + path: "" +``` + +Provide the appropriate `NFS_SERVER_IP` and `NFS_LOCATION_PATH`. + +g. Create a Kubernetes Persistent Volume Claim to bind with the Kubernetes Persistent Volume created in step e. For example, append the following entry +to the file `/is/identity-server-volume-claim.yaml`: + +``` +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: identity-server-additional-config-volume-claim +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: "" + selector: + matchLabels: + purpose: is-additional-configs +``` + +h. Update the appropriate Kubernetes [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) resource(s). +For example in the discussed scenario, update the volumes (`spec.template.spec.volumes`) and volume mounts (`spec.template.spec.containers[wso2is].volumeMounts`) in +`/is/identity-server-deployment.yaml` file as follows: + +``` +volumeMounts: +... +- name: is-additional-config-storage-volume + mountPath: "/home/wso2carbon/wso2-server-volume" + +volumes: +... +- name: is-additional-config-storage-volume + persistentVolumeClaim: + claimName: identity-server-additional-config-volume-claim +``` + +i. Deploy the Kubernetes resources as defined in section **Quick Start Guide** for a clustered deployment of WSO2 Identity Server. diff --git a/helm/is-with-analytics/README.md b/helm/is-with-analytics/README.md index 56d9f9a9..da09347b 100644 --- a/helm/is-with-analytics/README.md +++ b/helm/is-with-analytics/README.md @@ -1,101 +1,139 @@ -# Helm Charts for deployment of WSO2 Identity Server with Analytics +# Helm Chart for deployment of WSO2 Identity Server with WSO2 Identity Server Analytics + +## Contents + +* [Prerequisites](#prerequisites) +* [Quick Start Guide](#quick-start-guide) ## Prerequisites -In order to use WSO2 Helm resources, you need an active WSO2 subscription. If you do not possess an active WSO2 + +* In order to use WSO2 Helm resources, you need an active WSO2 subscription. If you do not possess an active WSO2 subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Helm](https://github.com/kubernetes/helm/blob/master/docs/install.md) -(and Tiller) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) in order to run the +(and Tiller) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (compatible with v1.10) in order to run the steps provided in the following quick start guide.

+* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/).

+ * Install [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/). This can be easily done via ``` helm install stable/nginx-ingress --name nginx-wso2is-analytics --set rbac.create=true ``` + ## Quick Start Guide >In the context of this document,
>* `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
>* `HELM_HOME` will refer to `/helm/is-with-analytics`.
-##### 1. Checkout Kubernetes Resources for WSO2 Identity server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository. ``` git clone https://github.com/wso2/kubernetes-is.git ``` -##### 2. Provide configurations: +##### 2. Setup a Network File System (NFS) to be used for persistent storage. + +Create and export unique directories within the NFS server instance for each of the following Kubernetes Persistent Volume +resources defined in the `/is-conf/values.yaml` file: + +* `sharedDeploymentLocationPath` +* `sharedTenantsLocationPath` +* `analytics1DataLocationPath` +* `analytics2DataLocationPath` +* `analytics1LocationPath` +* `analytics2LocationPath` + +Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. + + ``` + sudo chown -R wso2carbon:wso2 + ``` + +Grant read-write-execute permissions to the `wso2carbon` user, for each of the previously created directories. + + ``` + chmod -R 700 + ``` + +##### 3. Provide configurations. -1. The default product configurations are available at `/is-with-analytics-conf/confs` folder. Change the +a. The default product configurations are available at `/is-with-analytics-conf/confs` folder. Change the configurations as necessary. -2. Open the `/is-with-analytics-conf/values.yaml` and provide the following values. - - `username`: Username of your Free Trial Subscription
- `password`: Password of your Free Trial Subscription
- `email`: Docker email
- `namespace`: Namespace
- `svcaccount`: Service Account
- `serverIp`: NFS Server IP
- `locationPath`: NFS location path
- `sharedDeploymentLocationPath`: NFS shared deployment directory(/repository/deployment) location for IS
- `sharedTenantsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS
- `analytics1DataLocationPath`: NFS volume for Indexed data for Analytics node 1(/repository/data)
- `analytics2DataLocationPath`: NFS volume for Indexed data for Analytics node 2(/repository/data)
- `analytics1LocationPath`: NFS volume for Analytics data for Analytics node 1(/repository/analytics)
- `analytics2LocationPath`: NFS volume for Analytics data for Analytics node 2(/repository/analytics) - -3. Open the `/is-with-analytics-deployment/values.yaml` and provide the following values. - - `namespace`: Namespace
- `svcaccount`: Service Account +b. Open the `/is-with-analytics-conf/values.yaml` and provide the following values. + +| Parameter | Description | +|---------------------------------|-------------------------------------------------------------------------------------------| +| `username` | Your WSO2 username | +| `password` | Your WSO2 password | +| `email` | Docker email | +| `namespace` | Kubernetes Namespace in which the resources are deployed | +| `svcaccount` | Kubernetes Service Account in the `namespace` to which product instance pods are attached | +| `serverIp` | NFS Server IP | +| `sharedDeploymentLocationPath` | NFS shared deployment directory(`/repository/deployment`) location for EI | +| `sharedTenantsLocationPath` | NFS shared tenants directory(`/repository/tenants`) location for EI | +| `analytics1DataLocationPath` | NFS volume for Indexed data for Analytics node 1(`/repository/data`) | +| `analytics2DataLocationPath` | NFS volume for Indexed data for Analytics node 2(`/repository/data`) | +| `analytics1LocationPath` | NFS volume for Analytics data for Analytics node 1(`/repository/analytics`) | +| `analytics2LocationPath` | NFS volume for Analytics data for Analytics node 2(`/repository/analytics`) | + +c. Open the `/is-with-analytics-deployment/values.yaml` and provide the following values. -##### 3. Deploy the configurations: +| Parameter | Description | +|---------------------------------|-------------------------------------------------------------------------------------------| +| `namespace` | Kubernetes Namespace in which the resources are deployed | +| `svcaccount` | Kubernetes Service Account in the `namespace` to which product instance pods are attached | + + +##### 4. Deploy the configurations. ``` helm install --name /is-with-analytics-conf ``` -##### 4. Deploy MySQL: -If there is an external product database(s), add those configurations as stated at `step 2.1`. Otherwise, run the below - command to create the product database. +##### 5. Deploy product database(s) using MySQL in Kubernetes. + ``` -helm install --name wso2is-with-analytics-rdbms-service -f /mysql/values.yaml -stable/mysql --namespace +helm install --name wso2is-with-analytics-rdbms-service -f /mysql/values.yaml stable/mysql --namespace ``` -`NAMESPACE` should be same as `step 2.2`. -##### 5. Deploy WSO2 Enterprise Identity server: +`NAMESPACE` should be same as in `step 3.b`. + +For a serious deployment (e.g. production grade setup), it is recommended to connect product instances to a user owned and managed RDBMS instance. + +##### 6. Deploy WSO2 Identity Server with WSO2 Identity Server Analytics. ``` helm install --name /is-with-analytics-deployment ``` -##### 6. Access Management Console: +##### 7. Access Management Console. -Default deployment will expose two publicly accessible hosts, namely:
-1. `wso2is` - To expose Administrative services and Management Console
-2. `wso2is-analytics` - To expose Analytics server
+Default deployment will expose `wso2is` and `wso2is-analytics` hosts (to expose Administrative services and Management Console). -To access the console in a test environment, +To access the console in the environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing -n wso2`). +a. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses. -e.g. +``` +kubectl get ing +``` ``` -NAME HOSTS ADDRESS PORTS AGE -wso2is-with-analytics-is-analytics-ingress wso2is-analytics 80, 443 9m -wso2is-with-analytics-is-ingress wso2is 80, 443 9m +NAME HOSTS ADDRESS PORTS AGE +wso2is-with-analytics-is-analytics-ingress wso2is-analytics 80, 443 3m +wso2is-with-analytics-is-ingress wso2is 80, 443 3m ``` -2. Add the above two hosts as entries in /etc/hosts file as follows: +b. Add the above host as an entry in /etc/hosts file as follows: ``` - wso2is wso2is-analytics + wso2is ``` -3. Try navigating to `https://wso2is/carbon` from your favorite browser. +c. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. diff --git a/helm/is/README.md b/helm/is/README.md index 26620066..4340cc58 100644 --- a/helm/is/README.md +++ b/helm/is/README.md @@ -1,4 +1,9 @@ -# Helm Charts for deployment of WSO2 Identity Server +# Helm Chart for deployment of WSO2 Identity Server + +## Contents + +* [Prerequisites](#prerequisites) +* [Quick Start Guide](#quick-start-guide) ## Prerequisites @@ -6,89 +11,117 @@ subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Helm](https://github.com/kubernetes/helm/blob/master/docs/install.md) -(and Tiller) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) in order to run the +(and Tiller) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (compatible with v1.10) in order to run the steps provided in the following quick start guide.

+* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/).

+ * Install [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/). This can be easily done via ``` helm install stable/nginx-ingress --name nginx-wso2is --set rbac.create=true ``` + ## Quick Start Guide >In the context of this document,
>* `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
>* `HELM_HOME` will refer to `/helm/is`.
-##### 1. Checkout Kubernetes Resources for WSO2 Identity server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository. ``` git clone https://github.com/wso2/kubernetes-is.git ``` -##### 2. Provide configurations: +##### 2. Setup a Network File System (NFS) to be used for persistent storage. + +Create and export unique directories within the NFS server instance for each of the following Kubernetes Persistent Volume +resources defined in the `/is-conf/values.yaml` file: + +* `sharedDeploymentLocationPath` +* `sharedTenantsLocationPath` + +Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. + + ``` + sudo chown -R wso2carbon:wso2 + ``` + +Grant read-write-execute permissions to the `wso2carbon` user, for each of the previously created directories. + + ``` + chmod -R 700 + ``` + +##### 3. Provide configurations. -1. The default product configurations are available at `/is-conf/confs` folder. Change the +a. The default product configurations are available at `/is-conf/confs` folder. Change the configurations as necessary. -2. Open the `/is-conf/values.yaml` and provide the following values. +b. Open the `/is-conf/values.yaml` and provide the following values. - `username`: Username of your Free Trial Subscription
- `password`: Password of your Free Trial Subscription
- `email`: Docker email
- `namespace`: Namespace
- `svcaccount`: Service Account
- `serverIp`: NFS Server IP
- `sharedDeploymentLocationPath`: NFS shared deployment directory(/repository/deployment) location for IS
- `sharedTenantsLocationPath`: NFS shared tenants directory(/repository/tenants) location for IS - -3. Open the `/is-deployment/values.yaml` and provide the following values. +| Parameter | Description | +|---------------------------------|-------------------------------------------------------------------------------------------| +| `username` | Your WSO2 username | +| `password` | Your WSO2 password | +| `email` | Docker email | +| `namespace` | Kubernetes Namespace in which the resources are deployed | +| `svcaccount` | Kubernetes Service Account in the `namespace` to which product instance pods are attached | +| `serverIp` | NFS Server IP | +| `sharedDeploymentLocationPath` | NFS shared deployment directory(`/repository/deployment`) location for EI | +| `sharedTenantsLocationPath` | NFS shared tenants directory(`/repository/tenants`) location for EI | - `namespace`: Namespace
- `svcaccount`: Service Account +c. Open the `/is-deployment/values.yaml` and provide the following values. -##### 3. Deploy the configurations: +| Parameter | Description | +|---------------------------------|-------------------------------------------------------------------------------------------| +| `namespace` | Kubernetes Namespace in which the resources are deployed | +| `svcaccount` | Kubernetes Service Account in the `namespace` to which product instance pods are attached | + +##### 4. Deploy the configurations. ``` helm install --name /is-conf ``` -##### 4. Deploy MySQL: -If there is an external product database(s), add those configurations as stated at `step 2.1`. Otherwise, run the below - command to create the product database. +##### 5. Deploy product database(s) using MySQL in Kubernetes. + ``` -helm install --name wso2is-rdbms-service -f /mysql/values.yaml -stable/mysql --namespace +helm install --name wso2is-rdbms-service -f /mysql/values.yaml stable/mysql --namespace ``` -`NAMESPACE` should be same as `step 2.2`. -##### 5. Deploy WSO2 Enterprise Identity server: +`NAMESPACE` should be same as in `step 3.b`. + +For a serious deployment (e.g. production grade setup), it is recommended to connect product instances to a user owned and managed RDBMS instance. + +##### 6. Deploy WSO2 Identity server. ``` helm install --name /is-deployment ``` -##### 6. Access Management Console: +##### 7. Access Management Console. -Default deployment will expose following publicly accessible host, namely:
-1. `wso2is` - To expose Administrative services and Management Console
+Default deployment will expose `wso2is` host (to expose Administrative services and Management Console). -To access the console in a test environment, +To access the console in the environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing -n wso2`). +a. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses. -e.g. +``` +kubectl get ing +``` ``` -NAME HOSTS ADDRESS PORTS AGE -wso2is-ingress wso2is 80, 443 9m +NAME HOSTS ADDRESS PORTS AGE +wso2is-ingress wso2is 80, 443 3m ``` -2. Add the above two hosts as entries in /etc/hosts file as follows: +b. Add the above host as an entry in /etc/hosts file as follows: ``` wso2is ``` -3. Try navigating to `https://wso2is/carbon` from your favorite browser. - +c. Try navigating to `https://wso2is/carbon` from your favorite browser. diff --git a/is-with-analytics/README.md b/is-with-analytics/README.md index 9a61801e..959bc2aa 100644 --- a/is-with-analytics/README.md +++ b/is-with-analytics/README.md @@ -1,26 +1,39 @@ # Kubernetes Resources for deployment of WSO2 Identity Server with WSO2 Identity Server Analytics -Core Kubernetes resources for a clustered deployment of WSO2 Identity Server with WSO2 Identity Server Analytics. +Core Kubernetes resources for a [clustered deployment of WSO2 Identity Server with WSO2 Identity Server Analytics](https://docs.wso2.com/display/IS560/Setting+Up+Deployment+Pattern+2). ![A clustered deployment WSO2 Identity Server with Identity Server Analytics support](is-with-analytics.png) +## Contents + +* [Prerequisites](#prerequisites) +* [Quick Start Guide](#quick-start-guide) + ## Prerequisites -* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 -subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active +WSO2 subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+ +* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (compatible with v1.10) +in order to run the steps provided in the following quick start guide.

-* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) -(version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) -in order to run the steps provided
in the following quick start guide.

+* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/).

-* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/)

+* A pre-configured Network File System (NFS) to be used as the persistent volume for artifact sharing and persistence. +In the NFS server instance, create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802`. +Add the `wso2carbon` user to the group `wso2`. + +``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` ## Quick Start Guide >In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository. ``` git clone https://github.com/wso2/kubernetes-is.git @@ -33,13 +46,13 @@ kubectl create namespace wso2 kubectl create serviceaccount wso2svc-account -n wso2 ``` -Then, switch the context to new `wso2` namespace from `default` namespace. +Then, switch the context to new `wso2` namespace. ``` kubectl config set-context $(kubectl config current-context) --namespace=wso2 ``` -##### 3. Create a Kubernetes Secret for pulling the required Docker images from [`WSO2 Docker Registry`](https://docker.wso2.com): +##### 3. Create a Kubernetes Secret for pulling the required Docker images from [`WSO2 Docker Registry`](https://docker.wso2.com). Create a Kubernetes Secret named `wso2creds` in the cluster to authenticate with the WSO2 Docker Registry, to pull the required images. @@ -53,7 +66,7 @@ kubectl create secret docker-registry wso2creds --docker-server=docker.wso2.com Please see [Kubernetes official documentation](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-in-the-cluster-that-holds-your-authorization-token) for further details. -##### 4. Setup product database(s): +##### 4. Setup product database(s). Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) on creating the required databases for the deployment. @@ -61,19 +74,19 @@ on creating the required databases for the deployment. Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in the following files: -* `KUBERNETES_HOME/is-with-analytics/confs/is/datasources/master-datasources.xml` -* `KUBERNETES_HOME/is-with-analytics/confs/is/datasources/bps-datasources.xml` -* `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-1/datasources/master-datasources.xml` -* `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-1/datasources/analytics-datasources.xml` -* `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-2/datasources/master-datasources.xml` -* `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-2/datasources/analytics-datasources.xml` +* `/is-with-analytics/confs/is/datasources/master-datasources.xml` +* `/is-with-analytics/confs/is/datasources/bps-datasources.xml` +* `/is-with-analytics/confs/is-analytics-1/datasources/master-datasources.xml` +* `/is-with-analytics/confs/is-analytics-1/datasources/analytics-datasources.xml` +* `/is-with-analytics/confs/is-analytics-2/datasources/master-datasources.xml` +* `/is-with-analytics/confs/is-analytics-2/datasources/analytics-datasources.xml` Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN44x/Configuring+master-datasources.xml) on configuring data sources. **Note**: * For **evaluation purposes**, you can use Kubernetes resources provided in the directory
-`KUBERNETES_HOME/is-with-analytics/extras/rdbms/mysql` for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is +`/is-with-analytics/extras/rdbms/mysql` for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is **not recommended** for a production setup. * For using these Kubernetes resources, @@ -84,12 +97,16 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN kubectl create configmap mysql-dbscripts --from-file=/is-with-analytics/extras/confs/mysql/dbscripts/ ``` - Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. - Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. - Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource - named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. + Here, a Network File System (NFS) is needed to be used for persisting MySQL DB data. + + Create and export a directory within the NFS server instance. - Then, deploy the persistent volume resource and volume claim as follows: + Provide read-write-execute permissions to other users for the created folder. + + Update the Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, + NFS server directory path (`NFS_LOCATION_PATH`) in `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. + + Deploy the persistent volume resource and volume claim as follows: ``` kubectl create -f /is-with-analytics/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml @@ -111,34 +128,25 @@ kubectl create --username=admin --password= -f /is-with-analytics/volumes/persistent-volumes.yaml` file. +Create and export unique directories within the NFS server instance for each Kubernetes Persistent Volume resource defined in the +`/is-with-analytics/volumes/persistent-volumes.yaml` file. -* `wso2is-with-analytics-shared-deployment-pv` -* `wso2is-with-analytics-shared-tenants-pv` -* `wso2is-with-analytics-is-analytics-data-pv-1` -* `wso2is-with-analytics-is-analytics-data-pv-2` -* `wso2is-with-analytics-is-analytics-pv-1` -* `wso2is-with-analytics-is-analytics-pv-2` - -Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. -Add `wso2carbon` user to the group `wso2`. +Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. ``` -groupadd --system -g 802 wso2 -useradd --system -g 802 -u 802 wso2carbon +sudo chown -R wso2carbon:wso2 ``` -Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +Grant read-write-execute permissions to the `wso2carbon` user, for each of the previously created directories. ``` -sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH -chmod -R 700 NFS_LOCATION_PATH +chmod -R 700 ``` +Update each Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, NFS server directory path (`NFS_LOCATION_PATH`). + Then, deploy the persistent volume resource and volume claim as follows: ``` @@ -147,7 +155,7 @@ kubectl create -f /is-with-analytics/is-analytics/identity-serv kubectl create -f /is-with-analytics/volumes/persistent-volumes.yaml ``` -##### 7. Create Kubernetes ConfigMaps for passing WSO2 product configurations into the Kubernetes cluster: +##### 7. Create Kubernetes ConfigMaps for passing WSO2 product configurations into the Kubernetes cluster. ``` kubectl create configmap identity-server-conf --from-file=/is-with-analytics/confs/is/conf/ @@ -171,7 +179,7 @@ kubectl create configmap is-analytics-2-conf-datasources --from-file=/is-with-analytics/confs/is-analytics-2/deployment/server/jaggeryapps/portal/configs ``` -##### 8. Create Kubernetes Services and Deployments for WSO2 Identity Server and Analytics: +##### 8. Create Kubernetes Services and Deployments for WSO2 Identity Server and Analytics. ``` kubectl create -f /is-with-analytics/is/identity-server-service.yaml @@ -183,7 +191,7 @@ kubectl create -f /is-with-analytics/is-analytics/identity-serv kubectl create -f /is-with-analytics/is-analytics/identity-server-analytics-service.yaml ``` -##### 9. Deploy Kubernetes Ingress resource: +##### 9. Deploy Kubernetes Ingress resource. The WSO2 Identity Server and Identity Server Analytics Kubernetes Ingress resources use the NGINX Ingress Controller. @@ -197,15 +205,17 @@ kubectl create -f /is-with-analytics/ingresses/identity-server- kubectl create -f /is-with-analytics/ingresses/identity-server-analytics-ingress.yaml ``` -##### 10. Access Management Consoles: +##### 10. Access Management Consoles. Default deployment will expose `wso2is` and `wso2is-analytics` hosts (to expose Administrative services and Management Console). To access the console in the environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing`). +a. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses. -e.g. +``` +kubectl get ing +``` ``` NAME HOSTS ADDRESS PORTS AGE @@ -213,16 +223,16 @@ wso2is-with-analytics-is-analytics-ingress wso2is-analytics wso2is-with-analytics-is-ingress wso2is 80, 443 3m ``` -2. Add the above host as an entry in /etc/hosts file as follows: +b. Add the above host as an entry in /etc/hosts file as follows: ``` wso2is-analytics wso2is ``` -3. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. +c. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. -##### 11. Scale up using `kubectl scale`: +##### 11. Scale up using `kubectl scale`. Default deployment runs a single replica (or pod) of WSO2 Identity server. To scale this deployment into any `` number of container replicas, upon your requirement, simply run following Kubernetes client command on the terminal. diff --git a/is-with-analytics/scripts/README.md b/is-with-analytics/scripts/README.md index 8c97dfe4..d42928b7 100644 --- a/is-with-analytics/scripts/README.md +++ b/is-with-analytics/scripts/README.md @@ -1,66 +1,70 @@ # Kubernetes Test Resources for deployment of WSO2 Identity Server with WSO2 Identity Server Analytics Kubernetes Test Resources for WSO2 Identity Server and Analytics contain artifacts, which can be used to test the core -Kubernetes resources provided for a clustered deployment of WSO2 Identity Server with WSO2 Identity Server Analytics. +Kubernetes resources provided for a [clustered deployment of WSO2 Identity Server with WSO2 Identity Server Analytics](https://docs.wso2.com/display/IS560/Setting+Up+Deployment+Pattern+2). + +## Contents + +* [Prerequisites](#prerequisites) +* [Quick Start Guide](#quick-start-guide) ## Prerequisites -* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 -subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active +WSO2 subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+ +* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (compatible with v1.10) +in order to run the steps provided in the following quick start guide.

+ +* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/).

+ +* A pre-configured Network File System (NFS) to be used as the persistent volume for artifact sharing and persistence. +In the NFS server instance, create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802`. +Add the `wso2carbon` user to the group `wso2`. -* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) -(version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) -in order to run the steps provided
in the following quick start guide.

+``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` -* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/)

- ## Quick Start Guide >In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository. ``` git clone https://github.com/wso2/kubernetes-is.git ``` -##### 2. Deploy Kubernetes Ingress resource: +##### 2. Deploy Kubernetes Ingress resource. The WSO2 Identity Server Kubernetes Ingress resource uses the NGINX Ingress Controller. In order to enable the NGINX Ingress controller in the desired cloud or on-premise environment, please refer the official documentation, [NGINX Ingress Controller Installation Guide](https://kubernetes.github.io/ingress-nginx/deploy/). -##### 3. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. +##### 3. Setup a Network File System (NFS) to be used for persistent storage. -Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of the following persistent volume resources -defined in the `/is-with-analytics/volumes/persistent-volumes.yaml` file. +Create and export unique directories within the NFS server instance for each Kubernetes Persistent Volume resource defined in the +`/is-with-analytics/volumes/persistent-volumes.yaml` file. -* `wso2is-with-analytics-shared-deployment-pv` -* `wso2is-with-analytics-shared-tenants-pv` -* `wso2is-with-analytics-is-analytics-pv-1` -* `wso2is-with-analytics-is-analytics-pv-2` -* `wso2is-with-analytics-is-analytics-data-pv-1` -* `wso2is-with-analytics-is-analytics-data-pv-2` - -Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. -Add `wso2carbon` user to the group `wso2`. +Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. ``` -groupadd --system -g 802 wso2 -useradd --system -g 802 -u 802 wso2carbon +sudo chown -R wso2carbon:wso2 ``` -Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +Grant read-write-execute permissions to the `wso2carbon` user, for each of the previously created directories. ``` -sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH -chmod -R 700 NFS_LOCATION_PATH +chmod -R 700 ``` -##### 4. Setup product database(s): +Update each Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, NFS server directory path (`NFS_LOCATION_PATH`). + +##### 4. Setup product database(s). For **evaluation purposes**, @@ -70,11 +74,15 @@ for deploying the product databases, using MySQL in Kubernetes. However, this ap * For using these Kubernetes resources, - Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. - Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. - Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource - named `wso2is-with-analytics-mysql-pv` in the file `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. - + Here, a Network File System (NFS) is needed to be used for persisting MySQL DB data. + + Create and export a directory within the NFS server instance. + + Provide read-write-execute permissions to other users for the created folder. + + Update the Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, + NFS server directory path (`NFS_LOCATION_PATH`) in `/is-with-analytics/extras/rdbms/volumes/persistent-volumes.yaml`. + In a **production grade setup**, * Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) @@ -83,18 +91,18 @@ In a **production grade setup**, Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in the following files: - * `KUBERNETES_HOME/is-with-analytics/confs/is/datasources/master-datasources.xml` - * `KUBERNETES_HOME/is-with-analytics/confs/is/datasources/bps-datasources.xml` - * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-1/datasources/master-datasources.xml` - * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-1/datasources/analytics-datasources.xml` - * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-2/datasources/master-datasources.xml` - * `KUBERNETES_HOME/is-with-analytics/confs/is-analytics-2/datasources/analytics-datasources.xml` + * `/is-with-analytics/confs/is/datasources/master-datasources.xml` + * `/is-with-analytics/confs/is/datasources/bps-datasources.xml` + * `/is-with-analytics/confs/is-analytics-1/datasources/master-datasources.xml` + * `/is-with-analytics/confs/is-analytics-1/datasources/analytics-datasources.xml` + * `/is-with-analytics/confs/is-analytics-2/datasources/master-datasources.xml` + * `/is-with-analytics/confs/is-analytics-2/datasources/analytics-datasources.xml` Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN44x/Configuring+master-datasources.xml) on configuring data sources. -##### 5. Deploy Kubernetes resources: +##### 5. Deploy Kubernetes resources. -Change directory to `KUBERNETES_HOME/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: +Change directory to `/is-with-analytics/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` ./deploy.sh --wso2-username= --wso2-password= --cluster-admin-password= @@ -118,7 +126,11 @@ Default deployment will expose `wso2is` and `wso2is-analytics` hosts (to expose To access the console in the environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing`). +a. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses. + +``` +kubectl get ing +``` e.g. @@ -128,14 +140,14 @@ wso2is-with-analytics-is-analytics-ingress wso2is-analytics wso2is-with-analytics-is-ingress wso2is 80, 443 3m ``` -2. Add the above host as an entry in /etc/hosts file as follows: +b. Add the above host as an entry in /etc/hosts file as follows: ``` wso2is-analytics wso2is ``` -3. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. +c. Try navigating to `https://wso2is/carbon` and `https://wso2is-analytics/carbon` from your favorite browser. ##### 7. Scale up using `kubectl scale`: diff --git a/is/README.md b/is/README.md index a58616cc..ce77e8e4 100644 --- a/is/README.md +++ b/is/README.md @@ -1,20 +1,34 @@ # Kubernetes Resources for deployment of WSO2 Identity Server -Core Kubernetes resources for a clustered deployment of WSO2 Identity Server. +Core Kubernetes resources for a [clustered deployment of WSO2 Identity Server](https://docs.wso2.com/display/IS560/Setting+Up+Deployment+Pattern+1). ![A clustered deployment WSO2 Identity Server](is.png) +## Contents + +* [Prerequisites](#prerequisites) +* [Quick Start Guide](#quick-start-guide) + + ## Prerequisites -* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 -subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active +WSO2 subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

-* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) -(version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) -in order to run the steps provided
in the following quick start guide.

+* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (compatible with v1.10) +in order to run the steps provided in the following quick start guide.

+ +* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/).

+ +* A pre-configured Network File System (NFS) to be used as the persistent volume for artifact sharing and persistence. +In the NFS server instance, create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802`. +Add the `wso2carbon` user to the group `wso2`. + +``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` -* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/)

- ## Quick Start Guide >In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) @@ -33,7 +47,7 @@ kubectl create namespace wso2 kubectl create serviceaccount wso2svc-account -n wso2 ``` -Then, switch the context to new `wso2` namespace from `default` namespace. +Then, switch the context to new `wso2` namespace. ``` kubectl config set-context $(kubectl config current-context) --namespace=wso2 @@ -61,15 +75,15 @@ on creating the required databases for the deployment. Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in the following files: -* `KUBERNETES_HOME/is/confs/is/datasources/master-datasources.xml` -* `KUBERNETES_HOME/is/confs/is/datasources/bps-datasources.xml` +* `/is/confs/is/datasources/master-datasources.xml` +* `/is/confs/is/datasources/bps-datasources.xml` Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN44x/Configuring+master-datasources.xml) on configuring data sources. **Note**: * For **evaluation purposes**, you can use Kubernetes resources provided in the directory
-`KUBERNETES_HOME/is/extras/rdbms/mysql` for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is +`/is/extras/rdbms/mysql` for deploying the product databases, using MySQL in Kubernetes. However, this approach of product database deployment is **not recommended** for a production setup. * For using these Kubernetes resources, @@ -80,12 +94,16 @@ Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN kubectl create configmap mysql-dbscripts --from-file=/is/extras/confs/mysql/dbscripts/ ``` - Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. - Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. - Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource - named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. + Here, a Network File System (NFS) is needed to be used for persisting MySQL DB data. + + Create and export a directory within the NFS server instance. - Then, deploy the persistent volume resource and volume claim as follows: + Provide read-write-execute permissions to other users for the created folder. + + Update the Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, + NFS server directory path (`NFS_LOCATION_PATH`) in `/is/extras/rdbms/volumes/persistent-volumes.yaml`. + + Deploy the persistent volume resource and volume claim as follows: ``` kubectl create -f /is/extras/rdbms/mysql/mysql-persistent-volume-claim.yaml @@ -107,37 +125,32 @@ kubectl create --username=admin --password= -f /is/volumes/persistent-volumes.yaml` file. +##### 6. Setup a Network File System (NFS) to be used for persistent storage. -* `wso2is-shared-deployment-pv` -* `wso2is-shared-tenants-pv` +Create and export unique directories within the NFS server instance for each Kubernetes Persistent Volume resource defined in the +`/is/volumes/persistent-volumes.yaml` file. -Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. -Add `wso2carbon` user to the group `wso2`. +Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. ``` -groupadd --system -g 802 wso2 -useradd --system -g 802 -u 802 wso2carbon +sudo chown -R wso2carbon:wso2 ``` -Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +Grant read-write-execute permissions to the `wso2carbon` user, for each of the previously created directories. ``` -sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH -chmod -R 700 NFS_LOCATION_PATH +chmod -R 700 ``` +Update each Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, NFS server directory path (`NFS_LOCATION_PATH`). + Then, deploy the persistent volume resource and volume claim as follows: ``` kubectl create -f /is/identity-server-volume-claims.yaml kubectl create -f /is/volumes/persistent-volumes.yaml ``` - + ##### 7. Create Kubernetes ConfigMaps for passing WSO2 product configurations into the Kubernetes cluster: ``` @@ -173,22 +186,24 @@ Default deployment will expose `wso2is` host (to expose Administrative services To access the console in the environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing`). +a. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses. -e.g. +``` +kubectl get ing +``` ``` NAME HOSTS ADDRESS PORTS AGE wso2is-ingress wso2is 80, 443 3m ``` -2. Add the above host as an entry in /etc/hosts file as follows: +b. Add the above host as an entry in /etc/hosts file as follows: ``` wso2is ``` -3. Try navigating to `https://wso2is/carbon` from your favorite browser. +c. Try navigating to `https://wso2is/carbon` from your favorite browser. ##### 11. Scale up using `kubectl scale`: diff --git a/is/scripts/README.md b/is/scripts/README.md index 03ccd375..63fa7a08 100644 --- a/is/scripts/README.md +++ b/is/scripts/README.md @@ -1,62 +1,70 @@ # Kubernetes Test Resources for deployment of WSO2 Identity Server Kubernetes Test Resources for WSO2 Identity Server contain artifacts, which can be used to test the core -Kubernetes resources provided for a clustered deployment of WSO2 Identity Server. +Kubernetes resources provided for a [clustered deployment of WSO2 Identity Server](https://docs.wso2.com/display/IS560/Setting+Up+Deployment+Pattern+1). + +## Contents + +* [Prerequisites](#prerequisites) +* [Quick Start Guide](#quick-start-guide) ## Prerequisites -* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active WSO2 -subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+* In order to use WSO2 Kubernetes resources, you need an active WSO2 subscription. If you do not possess an active +WSO2 subscription already, you can sign up for a WSO2 Free Trial Subscription from [here](https://wso2.com/free-trial-subscription).

+ +* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) (compatible with v1.10) +in order to run the steps provided in the following quick start guide.

+ +* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/).

+ +* A pre-configured Network File System (NFS) to be used as the persistent volume for artifact sharing and persistence. +In the NFS server instance, create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802`. +Add the `wso2carbon` user to the group `wso2`. -* Install [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), [Docker](https://www.docker.com/get-docker) -(version 17.09.0 or above) and [Kubernetes client](https://kubernetes.io/docs/tasks/tools/install-kubectl/) -in order to run the steps provided
in the following quick start guide.

+``` +groupadd --system -g 802 wso2 +useradd --system -g 802 -u 802 wso2carbon +``` -* An already setup [Kubernetes cluster](https://kubernetes.io/docs/setup/pick-right-solution/)

- ## Quick Start Guide >In the context of this document, `KUBERNETES_HOME` will refer to a local copy of the [`wso2/kubernetes-is`](https://github.com/wso2/kubernetes-is/) Git repository.
-##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository: +##### 1. Clone the Kubernetes Resources for WSO2 Identity Server Git repository. ``` git clone https://github.com/wso2/kubernetes-is.git ``` -##### 2. Deploy Kubernetes Ingress resource: +##### 2. Deploy Kubernetes Ingress resource. The WSO2 Identity Server Kubernetes Ingress resource uses the NGINX Ingress Controller. In order to enable the NGINX Ingress controller in the desired cloud or on-premise environment, please refer the official documentation, [NGINX Ingress Controller Installation Guide](https://kubernetes.github.io/ingress-nginx/deploy/). -##### 3. Setup a Network File System (NFS) to be used as the persistent volume for artifact sharing across Identity Server and Analytics instances. +##### 3. Setup a Network File System (NFS) to be used for persistent storage. -Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of the following persistent volume resources -defined in the `/is/volumes/persistent-volumes.yaml` file. +Create and export unique directories within the NFS server instance for each Kubernetes Persistent Volume resource defined in the +`/is/volumes/persistent-volumes.yaml` file. -* `wso2is-shared-deployment-pv` -* `wso2is-shared-tenants-pv` - -Create a Linux system user account named `wso2carbon` with user id `802` and a system group named `wso2` with group id `802` in the NFS node. -Add `wso2carbon` user to the group `wso2`. +Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. ``` -groupadd --system -g 802 wso2 -useradd --system -g 802 -u 802 wso2carbon +sudo chown -R wso2carbon:wso2 ``` -Then, grant ownership of the exported folder `NFS_LOCATION_PATH` (used for artifact sharing) to `wso2carbon` user and `wso2` group. -And grant read-write-execute permissions to owning `wso2carbon` user, for the folder `NFS_LOCATION_PATH`. +Grant read-write-execute permissions to the `wso2carbon` user, for each of the previously created directories. ``` -sudo chown -R wso2carbon:wso2 NFS_LOCATION_PATH -chmod -R 700 NFS_LOCATION_PATH +chmod -R 700 ``` -##### 4. Setup product database(s): +Update each Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, NFS server directory path (`NFS_LOCATION_PATH`). + +##### 4. Setup product database(s). For **evaluation purposes**, @@ -66,11 +74,15 @@ for deploying the product databases, using MySQL in Kubernetes. However, this ap * For using these Kubernetes resources, - Setup a Network File System (NFS) to be used as the persistent volume for persisting MySQL DB data. - Provide read-write-execute permissions to `other` users, for the folder `NFS_LOCATION_PATH`. - Update the NFS server IP (`NFS_SERVER_IP`) and export path (`NFS_LOCATION_PATH`) of persistent volume resource - named `wso2is-mysql-pv` in the file `/is/extras/rdbms/volumes/persistent-volumes.yaml`. - + Here, a Network File System (NFS) is needed to be used for persisting MySQL DB data. + + Create and export a directory within the NFS server instance. + + Provide read-write-execute permissions to other users for the created folder. + + Update the Kubernetes Persistent Volume resource with the corresponding NFS server IP (`NFS_SERVER_IP`) and exported, + NFS server directory path (`NFS_LOCATION_PATH`) in `/is/extras/rdbms/volumes/persistent-volumes.yaml`. + In a **production grade setup**, * Setup the external product databases. Please refer to WSO2 Identity Server's [official documentation](https://docs.wso2.com/display/IS560/Setting+Up+Separate+Databases+for+Clustering) @@ -79,14 +91,14 @@ In a **production grade setup**, Provide appropriate connection URLs, corresponding to the created external databases and the relevant driver class names for the data sources defined in the following files: - * `KUBERNETES_HOME/is/confs/is/datasources/master-datasources.xml` - * `KUBERNETES_HOME/is/confs/is/datasources/bps-datasources.xml` + * `/is/confs/is/datasources/master-datasources.xml` + * `/is/confs/is/datasources/bps-datasources.xml` Please refer WSO2's [official documentation](https://docs.wso2.com/display/ADMIN44x/Configuring+master-datasources.xml) on configuring data sources. ##### 5. Deploy Kubernetes resources: -Change directory to `KUBERNETES_HOME/is/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: +Change directory to `/is/scripts` and execute the `deploy.sh` shell script on the terminal, with the appropriate configurations as follows: ``` ./deploy.sh --wso2-username= --wso2-password= --cluster-admin-password= @@ -110,22 +122,24 @@ Default deployment will expose `wso2is` host (to expose Administrative services To access the console in the environment, -1. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses (using `kubectl get ing`). +a. Obtain the external IP (`EXTERNAL-IP`) of the Ingress resources by listing down the Kubernetes Ingresses. -e.g. +``` +kubectl get ing +``` ``` NAME HOSTS ADDRESS PORTS AGE wso2is-ingress wso2is 80, 443 3m ``` -2. Add the above host as an entry in /etc/hosts file as follows: +b. Add the above host as an entry in /etc/hosts file as follows: ``` wso2is ``` -3. Try navigating to `https://wso2is/carbon` from your favorite browser. +c. Try navigating to `https://wso2is/carbon` from your favorite browser. ##### 7. Scale up using `kubectl scale`: @@ -133,7 +147,7 @@ Default deployment runs a single replica (or pod) of WSO2 Identity server. To sc container replicas, upon your requirement, simply run following Kubernetes client command on the terminal. ``` -kubectl scale --replicas= -f /is-with-analytics/is/identity-server-deployment.yaml +kubectl scale --replicas= -f /is/identity-server-deployment.yaml ``` For example, If `` is 2, you are here scaling up this deployment from 1 to 2 container replicas. From cc247be89e8bf01e09080352790bebbe265f5803 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 11 Jul 2018 22:49:42 +0530 Subject: [PATCH 24/24] Update Helm is-with-analytics readme file --- helm/is-with-analytics/README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/helm/is-with-analytics/README.md b/helm/is-with-analytics/README.md index da09347b..d01e9d3a 100644 --- a/helm/is-with-analytics/README.md +++ b/helm/is-with-analytics/README.md @@ -37,14 +37,12 @@ git clone https://github.com/wso2/kubernetes-is.git ##### 2. Setup a Network File System (NFS) to be used for persistent storage. Create and export unique directories within the NFS server instance for each of the following Kubernetes Persistent Volume -resources defined in the `/is-conf/values.yaml` file: +resources defined in the `/is-with-analytics/values.yaml` file: * `sharedDeploymentLocationPath` * `sharedTenantsLocationPath` * `analytics1DataLocationPath` * `analytics2DataLocationPath` -* `analytics1LocationPath` -* `analytics2LocationPath` Grant ownership to `wso2carbon` user and `wso2` group, for each of the previously created directories. @@ -77,8 +75,6 @@ b. Open the `/is-with-analytics-conf/values.yaml` and provide the fol | `sharedTenantsLocationPath` | NFS shared tenants directory(`/repository/tenants`) location for EI | | `analytics1DataLocationPath` | NFS volume for Indexed data for Analytics node 1(`/repository/data`) | | `analytics2DataLocationPath` | NFS volume for Indexed data for Analytics node 2(`/repository/data`) | -| `analytics1LocationPath` | NFS volume for Analytics data for Analytics node 1(`/repository/analytics`) | -| `analytics2LocationPath` | NFS volume for Analytics data for Analytics node 2(`/repository/analytics`) | c. Open the `/is-with-analytics-deployment/values.yaml` and provide the following values.