├── .gitignore ├── README.md ├── SCK-DOCKER-KUBERNETES-2022-share.pdf ├── SCK-DOCKER-KUBERNETES-IN-PRACTICE.pdf ├── SCK-KUBERNETES-IN-PRACTICE.pdf ├── SCK-KUBERNETES-STATEFUL.pdf ├── SCK-KUBERNETES-WORKSHOP-WITH-JAVA.pdf ├── code ├── demo-spring-mongodb │ ├── .gitignore │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── k8s │ │ ├── boot-deployment.yaml │ │ ├── boot-service.yaml │ │ └── mongodb │ │ │ ├── mongo-controller.yaml │ │ │ └── mongo-service.yaml │ ├── settings.gradle │ └── src │ │ ├── main │ │ ├── docker │ │ │ └── Dockerfile │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── SpringbootKubernetesApplication.java │ │ │ │ ├── model │ │ │ │ ├── Address.java │ │ │ │ └── User.java │ │ │ │ ├── repository │ │ │ │ └── UserRepository.java │ │ │ │ └── web │ │ │ │ └── UserController.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── SpringbootKubernetesApplicationTests.java └── hello │ ├── Dockerfile │ └── hello.go ├── install-k8s ├── install_centos.txt ├── install_minikube.txt ├── install_ubuntu_16.txt └── instruction.txt ├── working-with-java ├── 01-basic │ ├── couchbase-service.yaml │ ├── couchbase-volume.yaml │ ├── instruction.txt │ ├── wildfly-deployment.yaml │ ├── wildfly-pod.yaml │ ├── wildfly-replica-set.yaml │ ├── wildfly-replication-controller.yaml │ └── wildfly-service.yaml ├── 02-web-app │ ├── instruction-deploy-app.txt │ └── k8s │ │ ├── boot-deployment.yaml │ │ ├── boot-service.yaml │ │ └── mongodb │ │ ├── mongo-controller.yaml │ │ └── mongo-service.yaml ├── 03-hpa │ ├── boot-deployment.yaml │ ├── boot-hpa.yaml │ ├── boot-service.yaml │ └── instruction.txt ├── 04-secret-configmap │ ├── boot-config-map.yaml │ ├── boot-deployment.yaml │ ├── boot-service.yaml │ ├── instruction.txt │ ├── mongo-controller.yaml │ └── mongo_secret.yaml └── 05-ingress │ ├── boot-deployment.yaml │ ├── boot-ingress.yaml │ ├── boot-service.yaml │ └── instruction.txt └── workshop ├── 01-hello ├── instruction.txt ├── instruction2.txt └── workshop_instruction.txt ├── 02-pod-service ├── expose │ ├── 01-host-network.yaml │ ├── 02-host-port.yaml │ ├── 03-nginx-pod.yaml │ ├── 03-node-port.yaml │ ├── 04-load-balance.yaml │ ├── 05-ingress.yaml │ └── expose-pod-service.txt ├── multiple-pod │ ├── database_pod.yml │ ├── database_service.yml │ ├── web_pod.yml │ ├── web_service.yml │ └── workshop_instruction.txt └── single-pod │ ├── hello_pod.yml │ ├── hello_service.yml │ └── workshop_instruction.txt ├── 03-replication-controller ├── hello_rc.yml ├── hello_service.yml └── workshop_instruction.txt ├── 04-deployment-and-replica-set ├── hello_deployment.yml ├── hello_service.yml └── workshop_instruction.txt ├── 05-volume ├── basic │ ├── empty_pod.yml │ ├── mongodb_hostpath_pod.yml │ └── workshop_instruction.txt ├── emptydir │ ├── demo_empty_dir.yaml │ └── instruction.txt ├── hostPath │ └── demo_hostpath.yaml ├── nfs │ ├── nginx_deployment.yml │ ├── nginx_service.yml │ ├── pv.yml │ ├── pvc.yml │ └── workshop_instruction.txt ├── persistent_volume │ ├── demo_pv.1.yaml │ └── demo_pv.yaml ├── persistent_volume_claim │ ├── instruction.txt │ ├── pv_01.yaml │ ├── pvc_01.yaml │ └── tomcat_pvc_01.yaml └── storage_class │ ├── pvc_gcp.yaml │ ├── sc_gcp.yaml │ └── tomcat_pvc_01.yaml ├── configmap ├── better │ ├── config.yaml │ ├── instruction.txt │ └── pod-with-volume-configmap.yaml ├── code │ ├── Dockerfile │ └── index.js ├── config_01.yaml ├── config_02.yaml ├── deployment_01.yaml ├── deployment_02.yaml ├── deployment_03.yaml └── instruction.txt ├── healthcheck ├── hello_deployment.yml └── hello_deployment_readiness.yml ├── jobs ├── cronjob.yaml ├── instruction.txt └── job.yaml ├── logging ├── basic_pod.yaml └── instruction.txt ├── namespace-label └── instruction.txt ├── note20180702 ├── kubernetes-dashboard.yaml └── note.txt ├── readiness-and-liveness ├── golang-http-server │ ├── Dockerfile │ ├── Dockerfile-release │ ├── Makefile │ ├── app.go │ ├── instruction.txt │ └── liveness.yaml ├── liveness_command.yaml ├── liveness_http.yaml └── liveness_tcp.yaml └── setup.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.key 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes in Practices (Docker to K8s) 2 | 3 | ## Topics 4 | * Cloud Native Application 5 | * DevOps 6 | * Continuous Delivery 7 | * Microservices 8 | * Containerization 9 | * Container design principle 10 | * Basic of Docker 11 | * Ecosystem 12 | * Docker Image 13 | * Docker Container 14 | * Docker Registry 15 | * Docker Network 16 | * Docker Compose 17 | * Basic of Kubernetes 18 | * Architecture of Kubernetes 19 | * Key features 20 | * Core concepts 21 | * Pods and Container 22 | * Service 23 | * Replication Controller (RC) 24 | * Deployment and ReplicaSet (RS) 25 | * Volume 26 | * EmptyDir 27 | * HostPath 28 | * Persistent Volume 29 | * Liveness and Readiness 30 | * Resource management and Horizontal Pods Autoscaler (HPA) 31 | * ConfigMap and Secret 32 | * Log and monitoring 33 | * Ingress Networking 34 | * StatefulSet 35 | 36 | ## Install Kubernetes cluster 37 | * [Installation](https://github.com/up1/workshop-k8s-setup) 38 | * Google Clound Compute Engine 39 | * Ansible 40 | * Manual or command-line 41 | 42 | ## Workshops 43 | * [Workshop with Docker](https://github.com/up1/workshop-continuous-testing) 44 | * ReactJS/Go/PostgreSQL 45 | * [Workshop Docker and Kubernetes #1](https://github.com/up1/workshop-docker-k8s-helm) 46 | * ReactJS/NodeJS/MongoDB 47 | * [Workshop Docker and Kubernetes #2](https://github.com/up1/demo-docker-k8s) 48 | * ReactJS/NodeJS/PostgreSQL 49 | * [Workshop with Go](https://github.com/up1/workshop-devops-go) 50 | * Java 51 | * [Hello with Spring Boot](https://github.com/up1/workshop-java-springboot-docker-k8s) 52 | * [Microservices with Spring Boot](https://github.com/up1/workshop-kubernetes-microservices) 53 | * [Workshop 2022/04/20](https://github.com/up1/workshop-java-docker-k8s-20220420) 54 | * [HDFS workshop](https://github.com/up1/workshop-docker-and-k8s) 55 | * [Docker with Python + Flask](https://github.com/up1/workshop-python-flask) 56 | 57 | ## Resources 58 | * https://kubernetes.io 59 | * [Docker Cheat Sheet](https://github.com/wsargent/docker-cheat-sheet) 60 | * [Benchmark results of Kubernetes network plugins (CNI) over 10Gbit/s network](https://itnext.io/benchmark-results-of-kubernetes-network-plugins-cni-over-10gbit-s-network-36475925a560) 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /SCK-DOCKER-KUBERNETES-2022-share.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/ff37bc4599b645df8bdc6de325fa364627fd46d5/SCK-DOCKER-KUBERNETES-2022-share.pdf -------------------------------------------------------------------------------- /SCK-DOCKER-KUBERNETES-IN-PRACTICE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/ff37bc4599b645df8bdc6de325fa364627fd46d5/SCK-DOCKER-KUBERNETES-IN-PRACTICE.pdf -------------------------------------------------------------------------------- /SCK-KUBERNETES-IN-PRACTICE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/ff37bc4599b645df8bdc6de325fa364627fd46d5/SCK-KUBERNETES-IN-PRACTICE.pdf -------------------------------------------------------------------------------- /SCK-KUBERNETES-STATEFUL.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/ff37bc4599b645df8bdc6de325fa364627fd46d5/SCK-KUBERNETES-STATEFUL.pdf -------------------------------------------------------------------------------- /SCK-KUBERNETES-WORKSHOP-WITH-JAVA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/ff37bc4599b645df8bdc6de325fa364627fd46d5/SCK-KUBERNETES-WORKSHOP-WITH-JAVA.pdf -------------------------------------------------------------------------------- /code/demo-spring-mongodb/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ -------------------------------------------------------------------------------- /code/demo-spring-mongodb/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '1.5.2.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | classpath('se.transmode.gradle:gradle-docker:1.2') 11 | } 12 | } 13 | 14 | apply plugin: 'java' 15 | apply plugin: 'eclipse' 16 | apply plugin: 'org.springframework.boot' 17 | apply plugin: 'docker' 18 | 19 | jar { 20 | baseName = 'springboot-kubernetes' 21 | version = '0.0.1-SNAPSHOT' 22 | } 23 | 24 | task buildDocker(type: Docker, dependsOn: build) { 25 | push = false 26 | applicationName = 'somkiat/spring-boot-example' 27 | dockerfile = file('src/main/docker/Dockerfile') 28 | doFirst { 29 | copy { 30 | from jar 31 | into stageDir 32 | } 33 | } 34 | } 35 | sourceCompatibility = 1.8 36 | 37 | repositories { 38 | mavenCentral() 39 | } 40 | 41 | 42 | dependencies { 43 | compile('org.springframework.boot:spring-boot-starter-web') 44 | compile('org.springframework.boot:spring-boot-starter-data-mongodb') 45 | testCompile('org.springframework.boot:spring-boot-starter-test') 46 | } 47 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/ff37bc4599b645df8bdc6de325fa364627fd46d5/code/demo-spring-mongodb/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /code/demo-spring-mongodb/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 06 21:03:17 AEDT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip 7 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/k8s/boot-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: spring-boot-service-deployment 5 | spec: 6 | replicas: 2 7 | template: 8 | metadata: 9 | labels: 10 | app: spring-boot-service 11 | spec: 12 | containers: 13 | - name: spring-boot-service 14 | image: somkiat/spring-boot-example 15 | ports: 16 | - containerPort: 8080 17 | env: 18 | - name: MONGO_URI 19 | value: mongo-service 20 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/k8s/boot-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-service 5 | spec: 6 | selector: 7 | app: spring-boot-service 8 | type: NodePort 9 | ports: 10 | - port: 8080 11 | targetPort: 8080 12 | 13 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/k8s/mongodb/mongo-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | name: mongo 6 | name: mongo-controller 7 | spec: 8 | replicas: 1 9 | template: 10 | metadata: 11 | labels: 12 | name: mongo 13 | spec: 14 | containers: 15 | - image: mongo 16 | name: mongo 17 | ports: 18 | - name: mongo 19 | containerPort: 27017 20 | hostPort: 27017 21 | volumeMounts: 22 | - name: mongo-persistent-storage 23 | mountPath: /data/db 24 | volumes: 25 | - name: mongo-persistent-storage 26 | hostPath: 27 | path: /data/storage/mongodb 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/k8s/mongodb/mongo-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | name: mongo 6 | name: mongo-service 7 | spec: 8 | ports: 9 | - port: 27017 10 | targetPort: 27017 11 | selector: 12 | name: mongo -------------------------------------------------------------------------------- /code/demo-spring-mongodb/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'demo' 2 | 3 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | VOLUME /tmp 3 | ADD springboot-kubernetes-0.0.1-SNAPSHOT.jar app.jar 4 | RUN sh -c 'touch /app.jar' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.data.mongodb.host=$MONGO_URI \ 7 | -jar /app.jar" ] -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/java/com/example/SpringbootKubernetesApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @SpringBootApplication 9 | public class SpringbootKubernetesApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringbootKubernetesApplication.class, args); 13 | } 14 | } 15 | 16 | @RestController 17 | class GreetingsController { 18 | 19 | @GetMapping(path = "/greeting") 20 | public String greeting() { 21 | return "hello from springboot"; 22 | } 23 | } -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/java/com/example/model/Address.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | /** 4 | * Created by achalise on 12/12/16. 5 | */ 6 | public class Address { 7 | private String street1; 8 | private String street2; 9 | private String town; 10 | private String postcode; 11 | private String state; 12 | 13 | public String getStreet1() { 14 | return street1; 15 | } 16 | 17 | public void setStreet1(String street1) { 18 | this.street1 = street1; 19 | } 20 | 21 | public String getStreet2() { 22 | return street2; 23 | } 24 | 25 | public void setStreet2(String street2) { 26 | this.street2 = street2; 27 | } 28 | 29 | public String getTown() { 30 | return town; 31 | } 32 | 33 | public void setTown(String town) { 34 | this.town = town; 35 | } 36 | 37 | public String getPostcode() { 38 | return postcode; 39 | } 40 | 41 | public void setPostcode(String postcode) { 42 | this.postcode = postcode; 43 | } 44 | 45 | public String getState() { 46 | return state; 47 | } 48 | 49 | public void setState(String state) { 50 | this.state = state; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/java/com/example/model/User.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | import org.springframework.data.annotation.Id; 4 | 5 | /** 6 | * Created by achalise on 12/12/16. 7 | */ 8 | public class User { 9 | @Id 10 | public String id; 11 | private String firstName; 12 | private String lastName; 13 | 14 | public String getEmail() { 15 | return email; 16 | } 17 | 18 | public void setEmail(String email) { 19 | this.email = email; 20 | } 21 | 22 | private String email; 23 | 24 | public String getFirstName() { 25 | return firstName; 26 | } 27 | 28 | public void setFirstName(String firstName) { 29 | this.firstName = firstName; 30 | } 31 | 32 | public String getLastName() { 33 | return lastName; 34 | } 35 | 36 | public void setLastName(String lastName) { 37 | this.lastName = lastName; 38 | } 39 | 40 | public Address getAddress() { 41 | return address; 42 | } 43 | 44 | public void setAddress(Address address) { 45 | this.address = address; 46 | } 47 | 48 | private Address address; 49 | 50 | public User() { 51 | 52 | } 53 | 54 | public User withFirstName(String firstName) { 55 | this.firstName = firstName; 56 | return this; 57 | } 58 | 59 | public User withLastName(String lastName) { 60 | this.lastName = lastName; 61 | return this; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/java/com/example/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.repository; 2 | 3 | import com.example.model.User; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | 6 | /** 7 | * Created by achalise on 12/12/16. 8 | */ 9 | public interface UserRepository extends MongoRepository { 10 | public User findByEmail(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/java/com/example/web/UserController.java: -------------------------------------------------------------------------------- 1 | package com.example.web; 2 | 3 | import com.example.model.Address; 4 | import com.example.model.User; 5 | import com.example.repository.UserRepository; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import java.util.List; 12 | 13 | @RestController 14 | @RequestMapping("/user") 15 | public class UserController { 16 | private Logger log = LoggerFactory.getLogger(UserController.class); 17 | 18 | @Autowired 19 | private UserRepository userRepository; 20 | 21 | @RequestMapping(method = RequestMethod.GET, value = "{id}") 22 | public @ResponseBody 23 | User retrieveUser(@PathVariable("id") String id) { 24 | log.info("Retrieving user with id: " + id); 25 | 26 | User user = userRepository.findOne(id); 27 | if(user == null) { 28 | user = new User(); 29 | user.setAddress(new Address()); 30 | user.setFirstName("Arun"); 31 | userRepository.save(user); 32 | } 33 | return user; 34 | } 35 | 36 | @RequestMapping(method = RequestMethod.POST) 37 | public @ResponseBody 38 | User addUser(@RequestBody User user) { 39 | user = userRepository.save(user); 40 | return user; 41 | } 42 | 43 | @RequestMapping(method = RequestMethod.GET) 44 | public @ResponseBody 45 | List retriveUsers() { 46 | log.info("Retrieving all users"); 47 | List users = userRepository.findAll(); 48 | return users; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.data.mongodb.port=27017 -------------------------------------------------------------------------------- /code/demo-spring-mongodb/src/test/java/com/example/SpringbootKubernetesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringbootKubernetesApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /code/hello/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.10-alpine as builder 2 | WORKDIR /src 3 | COPY hello.go . 4 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . 5 | 6 | FROM alpine:latest 7 | RUN apk --no-cache add ca-certificates 8 | WORKDIR /root/ 9 | COPY --from=builder /src/app . 10 | CMD ["./app"] 11 | -------------------------------------------------------------------------------- /code/hello/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "html" 6 | "log" 7 | "net/http" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 13 | name, _ := os.Hostname() 14 | fmt.Fprintf(w, "V3 Hello, %q on %v", html.EscapeString(r.URL.Path), name) 15 | }) 16 | 17 | log.Fatal(http.ListenAndServe(":8080", nil)) 18 | 19 | } 20 | -------------------------------------------------------------------------------- /install-k8s/install_centos.txt: -------------------------------------------------------------------------------- 1 | ## Install Docker CE 2 | https://docs.docker.com/install/linux/docker-ce/centos/#install-docker-ce-1 3 | 4 | ## Change CGROUP 5 | docker info | grep cgroup 6 | vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 7 | Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs" 8 | 9 | 10 | ### Install Kubeadm/Kubelet 11 | 1. Install Yum Repository 12 | 13 | cat < /etc/yum.repos.d/kubernetes.repo 14 | [kubernetes] 15 | name=Kubernetes 16 | baseurl=http://yum.kubernetes.io/repos/kubernetes-el7-x86_64 17 | enabled=1 18 | gpgcheck=1 19 | repo_gpgcheck=1 20 | gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg 21 | https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg 22 | EOF 23 | 24 | 25 | 2. Disable SELinux 26 | setenforce 0 27 | 28 | 3. Install from Yum 29 | 30 | yum install -y kubelet kubeadm kubectl kubernetes-cni 31 | 32 | 33 | 4. Enable docker and kubelet 34 | systemctl enable docker && systemctl start docker 35 | systemctl enable kubelet && systemctl start kubelet 36 | 37 | 5. Overlay 38 | lsmod | grep overlay 39 | overlay 40 | 41 | 6. Restart 42 | systemctl start docker 43 | systemctl start kubelet 44 | 45 | 7. Disable firewall 46 | systemctl stop firewalld 47 | 48 | ==== Installation Master and Workers ==== 49 | #MASTER 50 | sudo su - 51 | swapoff -a 52 | kubeadm init --kubernetes-version=v1.10.3 --pod-network-cidr=10.244.0.0/16 --apiserver-cert-extra-sans 157.179.16.71 53 | kubeadm init --kubernetes-version=v1.10.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.244.0.0/12 --ignore-preflight-errors=cri 54 | exit 55 | 56 | 57 | ## MASTER 58 | mkdir -p $HOME/.kube 59 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 60 | sudo chown $(id -u):$(id -g) $HOME/.kube/config 61 | 62 | ## Enable master to deploy pods 63 | kubectl taint nodes --all node-role.kubernetes.io/master- 64 | 65 | ## Cluster network 66 | kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 67 | kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.8.0/Documentation/kube-flannel-rbac.yml 68 | 69 | ## Tools in MASTER 70 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml 71 | kubectl apply -f https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/rbac/heapster-rbac.yaml 72 | kubectl apply -f https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/influxdb/heapster.yaml 73 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/influxdb.yaml 74 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/grafana.yaml 75 | kubectl create clusterrolebinding insecure-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard 76 | kubectl get pods --all-namespaces 77 | 78 | 79 | ## On Local :: Proxying API Server to localhost 80 | scp root@:/etc/kubernetes/admin.conf . 81 | scp root@167.99.79.135:/etc/kubernetes/admin.conf . 82 | kubectl --kubeconfig ./admin.conf proxy 83 | 84 | http://localhost:8001/api/v1 85 | http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 86 | http://localhost:8001/api/v1/namespaces/kube-system/services/monitoring-grafana:/proxy/ 87 | 88 | ## Disable master to deploy pods 89 | kubectl taint nodes master=DoNotSchedulePods:NoExecute 90 | kubectl taint nodes docker01 master=DoNotSchedulePods:NoExecute 91 | 92 | ## Worker 93 | sudo su - 94 | swapoff -a 95 | kubeadm join 10.148.0.3:6443 --token b963d6.7zr3omm5kvu80ege --discovery-token-ca-cert-hash sha256:4a009b347760ce963225b32c7d2f27253b3e6740c7a0102a93afb5abf1a43f24 96 | exit 97 | 98 | ## Deploy 99 | kubectl run nginx --image=nginx --port 80 100 | kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort 101 | kubectl scale deployment/nginx --replicas=5 102 | 103 | kubectl get services 104 | kubectl delete service nginx 105 | kubectl get deployments 106 | kubectl delete deployment nginx 107 | 108 | curl http://10.148.0.3:32765 109 | curl http://10.148.0.2:32765 110 | curl http://10.148.0.2:32765 111 | 112 | 113 | 114 | kubectl delete node node-02 115 | kubectl delete node node-03 116 | kubectl drain node-01 --delete-local-data --force --ignore-daemonsets 117 | kubectl delete node node-01 118 | 119 | 120 | #Remove kubernetes 121 | kubeadm reset 122 | sudo apt-get purge kubeadm kubectl kubelet kubernetes-cni kube* 123 | sudo apt-get autoremove 124 | sudo rm -rf ~/.kube 125 | -------------------------------------------------------------------------------- /install-k8s/install_minikube.txt: -------------------------------------------------------------------------------- 1 | 0. Install VirtualBox 2 | https://www.virtualbox.org/wiki/Downloads 3 | 4 | 1. Install minikube 5 | https://github.com/kubernetes/minikube/releases 6 | 7 | $minikube get-k8s-versions 8 | $minikube start 9 | $minikube start --kubernetes-version="v1.9.4" 10 | $minikube status 11 | $minikube ip 12 | $minikube dashboard 13 | $minikube dashboard --url=true 14 | 15 | 2. Install Kubernetes CLI (kubectl) 16 | https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl-binary-via-curl 17 | 18 | $kubectl cluster-info 19 | $kubectl version 20 | $kubectl get nodes 21 | -------------------------------------------------------------------------------- /install-k8s/install_ubuntu_16.txt: -------------------------------------------------------------------------------- 1 | # Install K8s Server 2 | cd /usr/lib/python3/dist-packages 3 | cp apt_pkg.cpython-35m-x86_64-linux-gnu.so apt_pkg.so 4 | 5 | 6 | # Install docker 7 | sudo apt update && apt upgrade -y 8 | sudo apt install linux-image-extra-virtual ca-certificates curl software-properties-common -y 9 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 10 | sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 11 | $(lsb_release -cs) \ 12 | stable" 13 | sudo apt update 14 | sudo apt install docker-ce -y 15 | 16 | 17 | # Install k8s server 18 | sudo apt update 19 | sudo apt-get install -y apt-transport-https 20 | curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - 21 | 22 | sudo su 23 | cat < /etc/apt/sources.list.d/kubernetes.list 24 | deb http://apt.kubernetes.io/ kubernetes-xenial main 25 | EOF 26 | apt-get update 27 | exit 28 | 29 | sudo apt-get install -y kubelet kubeadm kubernetes-cni 30 | 31 | # Start master 32 | sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=10.148.0.2 --kubernetes-version stable-1.11 --ignore-preflight-errors all 33 | mkdir -p $HOME/.kube 34 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 35 | sudo chown $(id -u):$(id -g) $HOME/.kube/config 36 | 37 | # Networking 38 | kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml 39 | kubectl get all --namespace=kube-system 40 | 41 | # Join cluster 42 | sudo kubeadm join 10.148.0.2:6443 --token kj1bm0.x5pdh970pmibb7tm --discovery-token-ca-cert-hash sha256:f2c3560e521795321b6130cf2f8bbb0390b054259d4fdec6ef470c8fa26f87b1 --ignore-preflight-errors=all 43 | 44 | 45 | 46 | Reference 47 | https://medium.com/@Grigorkh/install-kubernetes-on-ubuntu-1ac2ef522a36 48 | -------------------------------------------------------------------------------- /install-k8s/instruction.txt: -------------------------------------------------------------------------------- 1 | ### Software requirements ### 2 | Ubuntu 16.04 LTS 3 | 4 | ## 1. Install Docker in all nodes 5 | sudo iptables-save > /tmp/iptables.conf 6 | sudo apt-get update 7 | sudo apt-get remove docker docker-engine 8 | sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common 9 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 10 | sudo apt-key fingerprint 0EBFCD88 11 | sudo add-apt-repository \ 12 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 13 | $(lsb_release -cs) \ 14 | stable" 15 | sudo apt-get update 16 | sudo apt-get -y install docker-ce 17 | sudo apt-get -y install nfs-kernel-server 18 | sudo apt-get -y install nfs-common 19 | sudo groupadd docker 20 | sudo usermod -aG docker $USER 21 | sudo systemctl enable docker 22 | 23 | ## 2. Install kubectl, kubelet and kubeadm in all nodes 24 | curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl 25 | chmod +x ./kubectl 26 | sudo mv ./kubectl /usr/local/bin/kubectl 27 | 28 | curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - 29 | sudo touch /etc/apt/sources.list.d/kubernetes.list 30 | sudo bash -c 'echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list' 31 | sudo apt-get update 32 | sudo apt-get install -y kubelet=1.10.0-00 kubeadm=1.10.0-00 33 | 34 | sudo iptables-restore < /tmp/iptables.conf 35 | 36 | #MASTER 37 | sudo su - 38 | swapoff -a 39 | kubeadm init --kubernetes-version=v1.10.3 --pod-network-cidr=10.244.0.0/16 --apiserver-cert-extra-sans 157.179.16.71 40 | kubeadm init --kubernetes-version=v1.10.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.244.0.0/12 --ignore-preflight-errors=cri 41 | exit 42 | 43 | 44 | ## MASTER 45 | mkdir -p $HOME/.kube 46 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 47 | sudo chown $(id -u):$(id -g) $HOME/.kube/config 48 | 49 | ## Enable master to deploy pods 50 | kubectl taint nodes --all node-role.kubernetes.io/master- 51 | 52 | ## Cluster network 53 | kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 54 | kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.8.0/Documentation/kube-flannel-rbac.yml 55 | 56 | ## Tools in MASTER 57 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml 58 | kubectl apply -f https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/rbac/heapster-rbac.yaml 59 | kubectl apply -f https://github.com/kubernetes/heapster/raw/master/deploy/kube-config/influxdb/heapster.yaml 60 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/influxdb.yaml 61 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/heapster/master/deploy/kube-config/influxdb/grafana.yaml 62 | kubectl create clusterrolebinding insecure-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard 63 | kubectl get pods --all-namespaces 64 | 65 | 66 | ## On Local :: Proxying API Server to localhost 67 | scp root@:/etc/kubernetes/admin.conf . 68 | scp root@167.99.79.135:/etc/kubernetes/admin.conf . 69 | kubectl --kubeconfig ./admin.conf proxy 70 | 71 | http://localhost:8001/api/v1 72 | http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 73 | http://localhost:8001/api/v1/namespaces/kube-system/services/monitoring-grafana:/proxy/ 74 | 75 | ## Disable master to deploy pods 76 | kubectl taint nodes master=DoNotSchedulePods:NoExecute 77 | kubectl taint nodes docker01 master=DoNotSchedulePods:Execute 78 | 79 | ## Worker 80 | sudo su - 81 | swapoff -a 82 | kubeadm join 10.148.0.3:6443 --token b963d6.7zr3omm5kvu80ege --discovery-token-ca-cert-hash sha256:4a009b347760ce963225b32c7d2f27253b3e6740c7a0102a93afb5abf1a43f24 83 | exit 84 | 85 | ## Deploy 86 | kubectl run nginx --image=nginx --port 80 87 | kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort 88 | kubectl scale deployment/nginx --replicas=5 89 | 90 | kubectl get services 91 | kubectl delete service nginx 92 | kubectl get deployments 93 | kubectl delete deployment nginx 94 | 95 | curl http://10.148.0.3:32765 96 | curl http://10.148.0.2:32765 97 | curl http://10.148.0.2:32765 98 | 99 | 100 | 101 | kubectl delete node node-02 102 | kubectl delete node node-03 103 | kubectl drain node-01 --delete-local-data --force --ignore-daemonsets 104 | kubectl delete node node-01 105 | 106 | 107 | #Remove kubernetes 108 | kubeadm reset 109 | sudo apt-get purge kubeadm kubectl kubelet kubernetes-cni kube* 110 | sudo apt-get autoremove 111 | sudo rm -rf ~/.kube 112 | 113 | 114 | 115 | #Resources 116 | https://kubernetes.io/docs/tasks/tools/install-kubeadm/#before-you-begin 117 | https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ 118 | -------------------------------------------------------------------------------- /working-with-java/01-basic/couchbase-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: couchbase-service 5 | spec: 6 | selector: 7 | app: couchbase-rc-pod 8 | ports: 9 | - name: admin 10 | port: 8091 11 | - name: query 12 | port: 8093 13 | --- 14 | apiVersion: v1 15 | kind: ReplicationController 16 | metadata: 17 | name: couchbase-rc 18 | spec: 19 | replicas: 2 20 | selector: 21 | app: couchbase-rc-pod 22 | template: 23 | metadata: 24 | labels: 25 | app: couchbase-rc-pod 26 | spec: 27 | containers: 28 | - name: couchbase 29 | image: couchbase 30 | ports: 31 | - containerPort: 8091 32 | -------------------------------------------------------------------------------- /working-with-java/01-basic/couchbase-volume.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: couchbase-pod 5 | labels: 6 | name: couchbase-pod 7 | spec: 8 | containers: 9 | - name: couchbase 10 | image: somkiat/couchbase:latest 11 | ports: 12 | - containerPort: 8091 13 | volumeMounts: 14 | - mountPath: /var/couchbase/lib 15 | name: couchbase-data 16 | volumes: 17 | - name: couchbase-data 18 | hostPath: 19 | path: /opt/data 20 | -------------------------------------------------------------------------------- /working-with-java/01-basic/instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Start Wildfly server with deployment 2 | $kubectl run hello-wildfly --image=jboss/wildfly:12.0.0.Final --port=8080 3 | $kubectl get deployments 4 | $kubectl describe deployments 5 | 6 | 2. Expose deployment as a service with target port (on container) 7 | $kubectl expose \ 8 | deployment hello-wildfly \ 9 | --name=hello-wildfly-service \ 10 | --port=8080 \ 11 | --target-port=8080 12 | 13 | 3. All exposed resources are available on kubernetes API server, 14 | If you want to access them, should using proxy (start proxy) 15 | 16 | $kubectl proxy 17 | 18 | Starting to serve on 127.0.0.1:8001 19 | Go to 20 | http://localhost:8001/api/v1/proxy/namespaces/default// 21 | eg. 22 | http://localhost:8001/api/v1/proxy/namespaces/default/services/hello-wildfly-service/index.html 23 | 24 | 4. Using configuration files 25 | 4.1 Create Pod 26 | $kubectl delete -f wildfly-pod.yml 27 | 28 | 4.2 Create Replication Controller 29 | $kubectl create -f wildfly-replication-controller.yml 30 | 31 | 4.3 Create Deployment 32 | $kubectl create -f wildfly-deployment.yml 33 | 34 | $kubectl get rc,pods 35 | 36 | 4.3 Create Service 37 | $kubectl create -f wildfly-service.yml 38 | 39 | 4.4 Scale RC 40 | kubectl scale rc wildfly-rc --replicas=4 41 | 42 | 4.5 Delete all resources 43 | $kubectl delete -f wildfly-service.yml 44 | $kubectl delete -f wildfly-deployment.yml 45 | $kubectl create -f wildfly-replication-controller.yml 46 | 47 | $kubectl delete service/wildfly-service rc/wildfly-rc 48 | -------------------------------------------------------------------------------- /working-with-java/01-basic/wildfly-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: wildfly-deployment 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: wildfly 10 | template: 11 | metadata: 12 | labels: 13 | app: wildfly 14 | spec: 15 | containers: 16 | - name: wildfly 17 | image: jboss/wildfly:10.1.0.Final 18 | ports: 19 | - containerPort: 8080 20 | -------------------------------------------------------------------------------- /working-with-java/01-basic/wildfly-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: wildfly-pod 5 | labels: 6 | name: wildfly-pod 7 | spec: 8 | containers: 9 | - name: wildfly 10 | image: jboss/wildfly:10.1.0.Final 11 | ports: 12 | - containerPort: 8080 13 | -------------------------------------------------------------------------------- /working-with-java/01-basic/wildfly-replica-set.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: ReplicaSet 3 | metadata: 4 | name: wildfly-rs 5 | spec: 6 | replicas: 2 7 | selector: 8 | matchLabels: 9 | app: wildfly-rs-pod 10 | matchExpressions: 11 | - {key: tier, operator: In, values: ["backend"]} 12 | - {key: environment, operator: NotIn, values: ["prod"]} 13 | template: 14 | metadata: 15 | labels: 16 | app: wildfly-rs-pod 17 | tier: backend 18 | environment: dev 19 | spec: 20 | containers: 21 | - name: wildfly 22 | image: jboss/wildfly:10.1.0.Final 23 | ports: 24 | - containerPort: 8080 25 | -------------------------------------------------------------------------------- /working-with-java/01-basic/wildfly-replication-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: wildfly-rc 5 | spec: 6 | replicas: 2 7 | selector: 8 | app: wildfly-rc-pod 9 | template: 10 | metadata: 11 | labels: 12 | app: wildfly-rc-pod 13 | spec: 14 | containers: 15 | - name: wildfly 16 | image: jboss/wildfly:10.1.0.Final 17 | ports: 18 | - containerPort: 8080 19 | -------------------------------------------------------------------------------- /working-with-java/01-basic/wildfly-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: wildfly-service 5 | spec: 6 | selector: 7 | app: wildfly-rc-pod 8 | ports: 9 | - name: web 10 | port: 8080 11 | -------------------------------------------------------------------------------- /working-with-java/02-web-app/instruction-deploy-app.txt: -------------------------------------------------------------------------------- 1 | 1. Build JAR file in Gradle project with Spring Boot 2 | $./gradlew bootRepackage 3 | 4 | 2. Build Docker image of Spring boot project 5 | $./gradlew buildDocker 6 | $docker image ls 7 | 8 | 3. Push Docker image to Docker Hub 9 | $docker login 10 | $docker push somkiat/spring-boot-example 11 | 12 | Try to check result in 13 | https://hub.docker.com/r/somkiat/spring-boot-example/ 14 | 15 | 4. Deploy application on Kubernetes 16 | 17 | 4.0 Prepare 18 | $minikube ssh 19 | >docker pull somkiat/spring-boot-example 20 | >docker pull mongo 21 | 22 | 4.1 Deploy mongodb 23 | $cd k8s/mongodb/ 24 | $kubectl create -f mongo-controller.yaml 25 | $kubectl create -f mongo-service.yaml 26 | 27 | # See result 28 | $kubectl get pod,rc,service 29 | 30 | 4.2 Deploy Spring boot application 31 | $cd k8s/ 32 | $kubectl create -f boot-deployment.yaml 33 | $kubectl create -f boot-service.yaml 34 | 35 | # See result 36 | $kubectl get pod,deployment,rs,service 37 | 38 | 4.3 Testing Spring boot service 39 | Open URL http://192.168.99.100:30265/greeting or 40 | $curl http://192.168.99.100:30265/greeting 41 | 42 | 4.4 Testing service with MongoDB 43 | # Insert data 44 | $curl -X POST -H "Content-Type: application/json" -d '{"firstName":"Somkiat","lastName":"Puisungnoen","email":"xxx@gmail.com"}' http://192.168.99.100:30265/user 45 | 46 | # Get all data in browser 47 | Open URL http://192.168.99.100:30265/user or 48 | $curl http://192.168.99.100:30265/user 49 | -------------------------------------------------------------------------------- /working-with-java/02-web-app/k8s/boot-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: spring-boot-service-deployment 5 | labels: 6 | app: spring-boot-service 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: spring-boot-service 12 | template: 13 | metadata: 14 | labels: 15 | app: spring-boot-service 16 | spec: 17 | containers: 18 | - name: spring-boot-service 19 | image: somkiat/spring-boot-example 20 | ports: 21 | - containerPort: 8080 22 | env: 23 | - name: MONGO_URI 24 | value: mongo-service 25 | -------------------------------------------------------------------------------- /working-with-java/02-web-app/k8s/boot-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-service 5 | labels: 6 | app: spring-boot-service 7 | spec: 8 | selector: 9 | app: spring-boot-service 10 | type: NodePort 11 | ports: 12 | - port: 8080 13 | targetPort: 8080 14 | 15 | -------------------------------------------------------------------------------- /working-with-java/02-web-app/k8s/mongodb/mongo-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | name: mongo 6 | name: mongo-controller 7 | spec: 8 | replicas: 1 9 | template: 10 | metadata: 11 | labels: 12 | name: mongo 13 | spec: 14 | containers: 15 | - image: mongo 16 | name: mongo 17 | ports: 18 | - name: mongo 19 | containerPort: 27017 20 | hostPort: 27017 -------------------------------------------------------------------------------- /working-with-java/02-web-app/k8s/mongodb/mongo-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | name: mongo 6 | name: mongo-service 7 | spec: 8 | ports: 9 | - port: 27017 10 | targetPort: 27017 11 | selector: 12 | name: mongo -------------------------------------------------------------------------------- /working-with-java/03-hpa/boot-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: spring-boot-service-deployment 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | app: spring-boot-service 11 | spec: 12 | containers: 13 | - name: spring-boot-service 14 | image: somkiat/spring-boot-example 15 | ports: 16 | - containerPort: 8080 17 | env: 18 | - name: MONGO_URI 19 | value: mongo-service 20 | resources: 21 | requests: 22 | cpu: "2m" 23 | -------------------------------------------------------------------------------- /working-with-java/03-hpa/boot-hpa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v2beta1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | name: podinfo 5 | spec: 6 | scaleTargetRef: 7 | apiVersion: extensions/v1beta1 8 | kind: Deployment 9 | name: spring-boot-service-deployment 10 | minReplicas: 1 11 | maxReplicas: 5 12 | metrics: 13 | - type: Resource 14 | resource: 15 | name: cpu 16 | targetAverageUtilization: 90 17 | 18 | -------------------------------------------------------------------------------- /working-with-java/03-hpa/boot-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-service 5 | spec: 6 | selector: 7 | app: spring-boot-service 8 | type: NodePort 9 | ports: 10 | - port: 8080 11 | targetPort: 8080 12 | nodePort: 32500 13 | -------------------------------------------------------------------------------- /working-with-java/03-hpa/instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Enable heapster in minikube 2 | $minikube addons enable heapster 3 | $minikube addons open heapster 4 | $minikube addons list 5 | 6 | # Install from Github 7 | $git clone https://github.com/kubernetes/heapster.git 8 | $cd heapster 9 | $kubectl create -f deploy/kube-config/influxdb/ 10 | $kubectl create -f deploy/kube-config/rbac/heapster-rbac.yaml 11 | 12 | # Check pods of heapster 13 | $kubectl get pods --all-namespaces 14 | $kubectl get service --all-namespaces 15 | 16 | 2. Create metric server 17 | $git clone https://github.com/kubernetes-incubator/metrics-server.git 18 | $cd metrics-server/ 19 | $kubectl create -f deploy/1.8+/ 20 | $kubectl get pods --all-namespaces 21 | 22 | 3. Create service and deployment of Spring boot service 23 | $kubectl create -f boot-deployment.yaml 24 | $kubectl create -f boot-service.yaml 25 | 26 | # Play with K8S 27 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/working-with-java/02-web-app/k8s/mongodb/mongo-controller.yaml 28 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/working-with-java/02-web-app/k8s/mongodb/mongo-service.yaml 29 | 30 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/working-with-java/03-hpa/boot-deployment.yaml 31 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/working-with-java/03-hpa/boot-service.yaml 32 | 33 | 4. Create Horizontal Pods Autoscale (HPA) 34 | $kubectl autoscale deployment/spring-boot-service-deployment --min=1 --max=5 --cpu-percent=5 35 | $kubectl get hpa 36 | $kubectl describe hpa 37 | 38 | 39 | 5. Load testing 40 | Try to create deployment=load-test to run load testing 41 | $kubectl run -i --tty load-test --image=busybox /bin/sh 42 | >wget -q -O- http://spring-boot-service.default.svc.cluster.local:8080/user 43 | >while true; sleep 5; do wget -q -O- http://spring-boot-service.default.svc.cluster.local:8080/user; done 44 | 45 | 6. Monitoring system 46 | $kubectl top nodes 47 | $kubectl top pods 48 | $kubectl get hpa 49 | $kubectl describe hpa 50 | 51 | And open kubernetes dashboard 52 | http://192.168.99.100:30000 53 | 54 | And open Grafana 55 | http://192.168.99.100:30002/dashboard/db/cluster?orgId=1 56 | 57 | 7. Delete all resources 58 | $kubectl delete hp 59 | $kubectl delete deployment 60 | $kubectl delete -f deploy/1.8+/ 61 | -------------------------------------------------------------------------------- /working-with-java/04-secret-configmap/boot-config-map.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: boot-configmap 5 | namespace: myservice 6 | labels: 7 | name: boot-configmap 8 | data: 9 | MONGO_URI: mongo-service 10 | -------------------------------------------------------------------------------- /working-with-java/04-secret-configmap/boot-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: spring-boot-service-deployment 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | app: spring-boot-service 11 | spec: 12 | containers: 13 | - name: spring-boot-service 14 | image: somkiat/spring-boot-example 15 | ports: 16 | - containerPort: 8080 17 | env: 18 | - name: MONGO_URI 19 | valueFrom: 20 | configMapKeyRef: 21 | name: boot-configmap 22 | key: MONGO_URI 23 | -------------------------------------------------------------------------------- /working-with-java/04-secret-configmap/boot-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-service 5 | spec: 6 | selector: 7 | app: spring-boot-service 8 | type: NodePort 9 | ports: 10 | - port: 8080 11 | targetPort: 8080 12 | 13 | -------------------------------------------------------------------------------- /working-with-java/04-secret-configmap/instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Create namespace 2 | $kubectl create namespace myservice 3 | $kubectl get namespace 4 | 5 | 2. Create configmap 6 | $kubectl create -f boot-config-map.yaml 7 | $kubectl get configmap --namespace myservice 8 | $kubectl describe configmap/boot-configmap --namespace myservice 9 | 10 | 3. Use configmap from deployment 11 | $kubectl create -f boot-deployment.yaml --namespace myservice 12 | $kubectl create -f boot-service.yaml --namespace myservice 13 | 14 | 4. Create secret 15 | $kubectl create -f boot-secret.yaml 16 | $kubectl get secret --namespace myservice 17 | $kubectl describe secret/boot-secret --namespace myservice 18 | -------------------------------------------------------------------------------- /working-with-java/04-secret-configmap/mongo-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | labels: 5 | name: mongo 6 | name: mongo-controller 7 | spec: 8 | replicas: 1 9 | template: 10 | metadata: 11 | labels: 12 | name: mongo 13 | spec: 14 | containers: 15 | - image: mongo 16 | name: mongo 17 | ports: 18 | - name: mongo 19 | containerPort: 27017 20 | hostPort: 27017 21 | volumeMounts: 22 | - name: mongo-persistent-storage 23 | mountPath: /data/db 24 | volumes: 25 | - name: mongo-persistent-storage 26 | hostPath: 27 | path: /data/storage/mongodb 28 | -------------------------------------------------------------------------------- /working-with-java/04-secret-configmap/mongo_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: mongo-secret 5 | namespace: myservice 6 | labels: 7 | name: mongo-secret 8 | type: Opaque 9 | data: 10 | username: cm9vdA== 11 | password: cGFzc3dvcmQ= 12 | -------------------------------------------------------------------------------- /working-with-java/05-ingress/boot-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: spring-boot-service-deployment 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | app: spring-boot-service 11 | spec: 12 | containers: 13 | - name: spring-boot-service 14 | image: somkiat/spring-boot-example 15 | ports: 16 | - containerPort: 8080 17 | env: 18 | - name: MONGO_URI 19 | value: mongo-service 20 | -------------------------------------------------------------------------------- /working-with-java/05-ingress/boot-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: ingresswebtest 5 | spec: 6 | rules: 7 | - host: first.cdg.com 8 | http: 9 | paths: 10 | - backend: 11 | serviceName: spring-boot-service 12 | servicePort: 80 13 | - host: second.cdg.com 14 | http: 15 | paths: 16 | - backend: 17 | serviceName: spring-boot-service 18 | servicePort: 80 19 | -------------------------------------------------------------------------------- /working-with-java/05-ingress/boot-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-service 5 | spec: 6 | selector: 7 | app: spring-boot-service 8 | type: NodePort 9 | ports: 10 | - port: 80 11 | name: http 12 | targetPort: 8080 13 | protocol: TCP 14 | -------------------------------------------------------------------------------- /working-with-java/05-ingress/instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Enable ingress in minikube 2 | $minikube addons list 3 | $minikube addons enable ingress 4 | 5 | 2. Create service and deployment of Spring boot service 6 | $kubectl create -f boot-deployment.yaml 7 | $kubectl create -f boot-service.yaml 8 | 9 | 3. Create Ingress 10 | $kubectl create -f boot-ingress.yaml 11 | $kubectl get ing -o wide 12 | $kubectl describe ing 13 | 14 | 4. Testing 15 | #Add host in Mac 16 | $echo "$(minikube ip) first.cdg.com second.cdg.com" | sudo tee -a /private/etc/hosts 17 | 18 | #Add host for Windows 19 | File c:\windows\system32\driver\etc\host 20 | first.cdg.com second.cdg.com 21 | 22 | $curl http://first.cdg.com/greeting 23 | $curl http://second.cdg.com/greeting 24 | -------------------------------------------------------------------------------- /workshop/01-hello/instruction.txt: -------------------------------------------------------------------------------- 1 | 0. Sound check 2 | #Check readiness 3 | $kubectl get nodes 4 | $kubectl describe node 5 | $kubectl get cs 6 | $kubectl get pods 7 | 8 | # SSH to minikube to pull images 9 | $minikube ip 10 | $minikube ssh 11 | >docker pull jboss/wildfly:12.0.0.Final 12 | >docker pull somkiat/hello:latest 13 | >docker pull labdocker/mysql:latest 14 | >docker pull labdocker/redis:latest 15 | >docker pull labdocker/cluster:webservice 16 | >docker pull labdocker/cluster:webcache_kubernetes 17 | 18 | 1. Create a container 19 | # Create with Replication controller 20 | $kubectl run hello --image=somkiat/hello:latest --port=8080 --generator=run/v1 21 | 22 | 2.1 List of pods 23 | $kubectl get pods 24 | $kubectl get pods -o wide 25 | $kubectl describe pods 26 | 27 | 2.2 List of ReplicationController 28 | $kubectl get replicationcontrollers 29 | $kubectl get rc 30 | 31 | 3. Expose the ReplicationController with service 32 | $kubectl expose rc hello --type=LoadBalancer --name hello-http 33 | 34 | 4. List of services 35 | $kubectl get services 36 | $kubectl get svc 37 | 38 | 5. Access service with Access (Minikube not support LoadBalancer) 39 | $minikube service hello-http 40 | 41 | 6. Scale up of Pods on the ReplicationController 42 | $kubectl scale rc hello --replicas=3 43 | $kubectl scale rc hello --replicas=1 44 | 45 | 7. List of ReplicationController and Pods 46 | $kubectl get rc 47 | $kubectl get pods 48 | 49 | 8. Testing 50 | $export SERVICE=192.168.99.100:32614 51 | $curl http://$SERVICE 52 | Hello, "/" on hello-wwsnh 53 | 54 | $curl http://$SERVICE 55 | Hello, "/" on hello-pqnzp 56 | 57 | $curl http://$SERVICE 58 | Hello, "/" on hello-lw2p7 59 | 60 | 9. Goto kubernetes dashboard 61 | $minikube dashboard 62 | $kubectl cluster-info 63 | 64 | 10. Delete all resources 65 | $kubectl delete rc 66 | $kubectl delete pod 67 | $kubectl delete service 68 | 69 | 11. Addons of minikube 70 | $minikube addons list 71 | $minikube addons enable heapster 72 | $minikube addons open heapster 73 | $kubectl get po,svc -n kube-system 74 | -------------------------------------------------------------------------------- /workshop/01-hello/instruction2.txt: -------------------------------------------------------------------------------- 1 | 1. Create a container 2 | Create with Deployment/ReplicaSet 3 | $kubectl run hello --image=somkiat/hello:latest --port=8080 4 | 5 | 2.1 List of pods 6 | $kubectl get pods 7 | $kubectl get pods -o wide 8 | $kubectl describe pods 9 | 10 | 2.2 List of Deployment and ReplicaSet 11 | $kubectl get deployments 12 | $kubectl get replicaset 13 | $kubectl get rs 14 | $kubectl describe deployments 15 | 16 | 2.3 View cluster events 17 | $kubectl get events 18 | $kubectl config view 19 | 20 | 3. Expose the Deployment with service 21 | $kubectl expose deployment hello --type=LoadBalancer --name hello-http 22 | 23 | 4. List of services 24 | $kubectl get services 25 | $kubectl get svc 26 | 27 | 5. Access service with Access (Minikube not support LoadBalancer) 28 | $minikube service hello-http 29 | 30 | 6. Scale up of Pods on the Deployment 31 | $kubectl scale deployment hello --replicas=3 32 | 33 | 7. List of Deployment and Pods 34 | $kubectl get deployment 35 | $kubectl get rs 36 | $kubectl get pods 37 | 38 | 8. Testing 39 | $export SERVICE=192.168.99.100:32614 40 | $curl http://$SERVICE 41 | Hello, "/" on hello-wwsnh 42 | 43 | $curl http://$SERVICE MacBook-Pro-2% curl http://192.168.99.100:32614/ 44 | Hello, "/" on hello-pqnzp 45 | 46 | $curl http://$SERVICE MacBook-Pro-2% curl http://192.168.99.100:32614/ 47 | Hello, "/" on hello-lw2p7 48 | 49 | 9. Goto kubernetes dashboard 50 | $minikube dashboard 51 | $kubectl cluster-info 52 | 53 | 10. Delete all resources 54 | $kubectl delete deployments 55 | $kubectl delete replicaset 56 | $kubectl delete pod 57 | $kubectl delete service 58 | -------------------------------------------------------------------------------- /workshop/01-hello/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Create a container 2 | $kubectl run hello --image=somkiat/hello --port=8080 --generator=run/v1 3 | 4 | 2.1 List of pods 5 | $kubectl get pods 6 | $kubectl get pods -o wide 7 | 8 | 2.2 List of ReplicationController 9 | $kubectl get replicationcontrollers 10 | $kubectl get rc 11 | 12 | 3. Expose the ReplicationController with service 13 | $kubectl expose rc hello --type=LoadBalancer --name hello-http 14 | $kubectl expose rc hello --type=NodePort --name hello-http 15 | 16 | 4. List of services 17 | $kubectl get services 18 | $kubectl get svc 19 | 20 | 5. Access service with Access (Minikube not support LoadBalancer) 21 | $minikube service hello-http 22 | 23 | 6. Scale up of Pods on the ReplicationController 24 | $kubectl scale rc hello --replicas=3 25 | 26 | 7. List of ReplicationController and Pods 27 | $kubectl get rc 28 | $kubectl get pods 29 | 30 | 8. Testing 31 | $export SERVICE=192.168.99.100:32614 32 | $curl http://$SERVICE 33 | Hello, "/" on hello-wwsnh 34 | 35 | $curl http://$SERVICE 36 | Hello, "/" on hello-pqnzp 37 | 38 | $curl http://$SERVICE 39 | Hello, "/" on hello-lw2p7 40 | 41 | 9. Goto dashboard 42 | $kubectl cluster-info 43 | $minikube dashboard 44 | 45 | 46 | 10. Delete resources 47 | $kubectl delete service/hello-http 48 | $kubectl delete rc/hello 49 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/01-host-network.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx 5 | spec: 6 | hostNetwork: true 7 | containers: 8 | - name: nginx 9 | image: nginx 10 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/02-host-port.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx 5 | spec: 6 | containers: 7 | - name: nginx 8 | image: nginx 9 | ports: 10 | - containerPort: 80 11 | hostPort: 8081 12 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/03-nginx-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx 5 | labels: 6 | name: nginx 7 | spec: 8 | containers: 9 | - name: nginx 10 | image: nginx 11 | ports: 12 | - containerPort: 80 13 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/03-node-port.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: nginx 5 | spec: 6 | type: NodePort 7 | ports: 8 | - port: 80 9 | nodePort: 30001 10 | selector: 11 | name: nginx 12 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/04-load-balance.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: nginx 5 | spec: 6 | type: LoadBalancer 7 | ports: 8 | - port: 80 9 | selector: 10 | name: nginx 11 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/05-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: nginx 5 | spec: 6 | rules: 7 | - host: nginx.kube.example.com 8 | http: 9 | paths: 10 | - web: 11 | serviceName: nginx 12 | servicePort: 80 13 | -------------------------------------------------------------------------------- /workshop/02-pod-service/expose/expose-pod-service.txt: -------------------------------------------------------------------------------- 1 | # Host network = true 2 | $kubectl create -f 01-host-network.yml 3 | $curl -v 192.168.99.100 4 | $kubectl delete -f 01-host-network.yml 5 | 6 | # Host port 7 | $kubectl create -f 02-host-port.yml 8 | $curl -v 192.168.99.100:8081 9 | $kubectl delete -f 02-host-port.yml 10 | 11 | # NodePort 12 | $kubectl create -f 03-nginx-pod.yaml 13 | $kubectl create -f 03-node-port.yaml 14 | $curl -v 192.168.99.100:30001 15 | $kubectl delete -f 03-nginx-pod.yaml 16 | $kubectl delete -f 03-node-port.yaml 17 | 18 | # Load Balance 19 | $kubectl create -f 03-nginx-pod.yaml 20 | $kubectl create -f 04-load-balance.yaml 21 | $kubectl get svc nginx 22 | $kubectl delete -f 04-load-balance.yaml 23 | $kubectl delete -f 03-nginx-pod.yaml 24 | 25 | # Ingress 26 | $kubectl create -f 03-nginx-pod.yaml 27 | $kubectl create -f 05-ingress.yaml 28 | curl nginx.kube.example.com 29 | -------------------------------------------------------------------------------- /workshop/02-pod-service/multiple-pod/database_pod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: "v1" 2 | kind: Pod 3 | metadata: 4 | name: maindb 5 | labels: 6 | name: "maindb" 7 | version: "1.0" 8 | module: "maindb" 9 | environment: "development" 10 | spec: 11 | containers: 12 | - name: maindb 13 | image: labdocker/mysql:latest 14 | ports: 15 | - containerPort: 3306 16 | protocol: TCP 17 | env: 18 | - 19 | name: "MYSQL_ROOT_PASSWORD" 20 | value: "password" 21 | -------------------------------------------------------------------------------- /workshop/02-pod-service/multiple-pod/database_service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: maindb 5 | labels: 6 | name: "maindb" 7 | version: "1.0" 8 | module: "maindb" 9 | environment: "development" 10 | spec: 11 | ports: 12 | - port: 3306 13 | targetPort: 3306 14 | selector: 15 | name: "maindb" 16 | version: "1.0" 17 | module: "maindb" 18 | environment: "development" 19 | -------------------------------------------------------------------------------- /workshop/02-pod-service/multiple-pod/web_pod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: web 5 | labels: 6 | name: "web" 7 | version: "1.0" 8 | module: "web" 9 | environment: "development" 10 | spec: 11 | containers: 12 | - name: cachedb 13 | image: labdocker/redis:latest 14 | ports: 15 | - containerPort: 6379 16 | protocol: TCP 17 | - name: webservice 18 | image: labdocker/cluster:webservice 19 | env: 20 | - name: "REDIS_HOST" 21 | value: "localhost" 22 | ports: 23 | - containerPort: 5000 24 | protocol: TCP 25 | - name: webcache 26 | image: labdocker/cluster:webcache_kubernetes 27 | ports: 28 | - containerPort: 80 29 | protocol: TCP 30 | -------------------------------------------------------------------------------- /workshop/02-pod-service/multiple-pod/web_service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: web 5 | labels: 6 | name: "web" 7 | version: "1.0" 8 | module: "Web" 9 | environment: "development" 10 | spec: 11 | selector: 12 | name: "web" 13 | version: "1.0" 14 | module: "web" 15 | environment: "development" 16 | type: NodePort 17 | ports: 18 | - port: 5000 19 | name: webservice 20 | targetPort: 5000 21 | protocol: TCP 22 | nodePort: 32500 23 | - port: 80 24 | name: webcache 25 | targetPort: 80 26 | protocol: TCP 27 | nodePort: 30500 28 | -------------------------------------------------------------------------------- /workshop/02-pod-service/multiple-pod/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Create database pods 2 | $kubectl create -f database_pod.yml --validate=false 3 | $kubectl get pods 4 | $kubectl get pods -w 5 | 6 | 2. Create database service 7 | $kubectl create -f database_service.yml --validate=false 8 | $kubectl get svc 9 | 10 | 3. Create web pods 11 | $kubectl create -f web_pod.yml --validate=false 12 | $kubectl get pods 13 | $kubectl get pods -w 14 | 15 | 4. Create web service 16 | $kubectl create -f web_service.yml --validate=false 17 | $kubectl get svc 18 | 19 | 5. Testing service 20 | $minikube status 21 | $minikube ip 22 | $export PORT=32500 23 | $export SERVICE=$(minikube ip):$PORT 24 | 25 | $curl http://$SERVICE 26 | $curl http://$SERVICE/init 27 | $curl -i -H "Content-Type: application/json" -X POST -d '{"uid": "1", "user":"User01", "descripe":"Slave"}' http://$SERVICE/users/insertuser 28 | 29 | $curl http://$SERVICE/users/1 30 | User01(Database Direct) 31 | 32 | $curl http://$SERVICE/users/1 33 | User01(Database Cache) 34 | 35 | 36 | 6. Delete pods and service 37 | $kubectl delete -f web_pod.yml 38 | $kubectl delete -f web_service.yml 39 | 40 | $kubectl delete -f database_pod.yml 41 | $kubectl delete -f database_service.yml 42 | -------------------------------------------------------------------------------- /workshop/02-pod-service/single-pod/hello_pod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: hello-web 5 | labels: 6 | name: web 7 | owner: somkiat 8 | version: "1.0" 9 | module: WebServer 10 | environment: development 11 | spec: 12 | containers: 13 | - name: hello-web 14 | image: somkiat/hello 15 | ports: 16 | - containerPort: 8080 17 | protocol: TCP 18 | -------------------------------------------------------------------------------- /workshop/02-pod-service/single-pod/hello_service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: hello 5 | labels: 6 | name: web 7 | owner: somkiat 8 | version: "1.0" 9 | module: WebServer 10 | environment: development 11 | spec: 12 | selector: 13 | name: web 14 | owner: somkiat 15 | version: "1.0" 16 | module: WebServer 17 | environment: development 18 | 19 | type: NodePort 20 | ports: 21 | - port: 8080 22 | name: http 23 | targetPort: 8080 24 | protocol: TCP 25 | -------------------------------------------------------------------------------- /workshop/02-pod-service/single-pod/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Create pods 2 | $kubectl create -f hello_pod.yml 3 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/workshop/02-pod-service/single-pod/hello_pod.yml 4 | $kubectl get pods 5 | 6 | 2. Create service 7 | $kubectl create -f hello_service.yml 8 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/workshop/02-pod-service/single-pod/hello_service.yml 9 | $kubectl get svc 10 | 11 | 3. Testing service 12 | $minikube status 13 | $minikube ip 14 | $export SERVICE=: 15 | $curl http://$SERVICE 16 | 17 | // Open forewall in Google Cloud 18 | $gcloud compute firewall-rules create xxx123 --allow tcp:32346 19 | 20 | 4. Description of pods and service 21 | $kubectl describe pod hello-web 22 | $kubectl describe service hello 23 | 24 | 5. Log of pods 25 | $kubectl logs hello-web -c hello-web 26 | 27 | 6. Access to container in pods 28 | $kubectl exec -it hello-web -c hello-web sh 29 | 30 | 7. Delete pods and service 31 | $kubectl delete -f hello_pod.yml 32 | $kubectl delete -f hello_service.yml 33 | -------------------------------------------------------------------------------- /workshop/03-replication-controller/hello_rc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: hello 5 | labels: 6 | name: web 7 | version: "1.0" 8 | module: WebServer 9 | environment: development 10 | spec: 11 | replicas: 3 12 | template: 13 | metadata: 14 | labels: 15 | name: web 16 | version: "1.0" 17 | module: WebServer 18 | environment: development 19 | spec: 20 | containers: 21 | - name: hello 22 | image: somkiat/hello:latest 23 | ports: 24 | - containerPort: 8080 25 | protocol: TCP 26 | -------------------------------------------------------------------------------- /workshop/03-replication-controller/hello_service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: hello 5 | labels: 6 | name: web 7 | version: "1.0" 8 | module: WebServer 9 | environment: development 10 | spec: 11 | selector: 12 | name: web 13 | version: "1.0" 14 | module: WebServer 15 | environment: development 16 | 17 | type: NodePort 18 | ports: 19 | - port: 8081 20 | name: http 21 | targetPort: 8080 22 | protocol: TCP 23 | nodePort: 32500 24 | -------------------------------------------------------------------------------- /workshop/03-replication-controller/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Create Replication Controller 2 | $kubectl create -f hello_rc.yml --validate=false 3 | $kubectl get po,rc 4 | 5 | 2. Create service 6 | $kubectl create -f hello_service.yml --validate=false 7 | $kubectl get svc 8 | 9 | 3. Testing service 10 | $minikube status 11 | $minikube ip 12 | $export SERVICE=:32500 13 | $curl http://$SERVICE 14 | 15 | 4. Delete some pods 16 | $kubectl get pods 17 | $kubectl delete pods hello-???? 18 | 19 | And check pods again !! 20 | 21 | 5. Scale Replication Controller 22 | $kubectl scale --replicas=5 rc/hello 23 | $kubectl scale --replicas=1 -f hello_rc.yml 24 | 25 | $kubectl describe rc hello 26 | 27 | 6. Delete pods and service 28 | $kubectl delete -f hello_rc.yml 29 | $kubectl delete -f hello_service.yml 30 | -------------------------------------------------------------------------------- /workshop/04-deployment-and-replica-set/hello_deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: hello 5 | labels: 6 | app: web 7 | spec: 8 | replicas: 1 9 | revisionHistoryLimit: 1 10 | selector: 11 | matchLabels: 12 | app: web 13 | template: 14 | metadata: 15 | labels: 16 | app: web 17 | spec: 18 | containers: 19 | - name: hello 20 | image: somkiat/hello:v2 21 | ports: 22 | - containerPort: 8080 23 | protocol: TCP 24 | -------------------------------------------------------------------------------- /workshop/04-deployment-and-replica-set/hello_service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: hello 5 | labels: 6 | app: web 7 | spec: 8 | selector: 9 | app: web 10 | 11 | type: NodePort 12 | ports: 13 | - port: 8080 14 | name: http 15 | targetPort: 8080 16 | protocol: TCP 17 | nodePort: 32500 18 | -------------------------------------------------------------------------------- /workshop/04-deployment-and-replica-set/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | 1. Create Deployment ans ReplicaSet 2 | $kubectl create -f hello_deployment.yml 3 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/workshop/04-deployment-and-replica-set/hello_deployment.yml 4 | $kubectl get deployment,rs 5 | $kubectl describe deployments 6 | $kubectl describe deployments hello 7 | 8 | 2. Create service 9 | $kubectl create -f hello_service.yml 10 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/workshop/04-deployment-and-replica-set/hello_service.yml 11 | $kubectl get svc 12 | 13 | 3. Testing service 14 | $minikube status 15 | $minikube ip 16 | $export SERVICE=:32500 17 | $curl http://$SERVICE 18 | 19 | 4. Update new version of Docker image on deployment 20 | $kubectl set image deployment/hello hello=somkiat/hello:v3 21 | 22 | 5. Check status of Rollout from deployment 23 | $kubectl rollout status deployment/hello 24 | 25 | $kubectl get deployment,rs,pods 26 | 27 | 6. Testing service again !! 28 | $minikube status 29 | $minikube ip 30 | $export SERVICE=:32500 31 | $curl http://$SERVICE 32 | 33 | 7. Check revision of change in History 34 | $kubectl rollout history deployment/hello 35 | 36 | 8. Try to rollback to revision=1 of rollout history 37 | $kubectl rollout undo deployment/hello --to-revision=1 38 | 39 | 9. Testing service again !! 40 | $minikube status 41 | $minikube ip 42 | $export SERVICE=:32500 43 | $curl http://$SERVICE 44 | 45 | 10. Scale a deployment 46 | $kubectl scale deployment hello --replicas=5 47 | $kubectl get deployment,rs 48 | 49 | 11. Delete pods and service 50 | $kubectl delete -f hello_deployment.yml 51 | $kubectl delete -f hello_service.yml 52 | -------------------------------------------------------------------------------- /workshop/05-volume/basic/empty_pod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: tryempty 5 | spec: 6 | containers: 7 | - image: luksa/fortune 8 | name: html-generator 9 | volumeMounts: 10 | - name: html 11 | mountPath: /var/htdocs 12 | 13 | - image: nginx:alpine 14 | name: web-server 15 | volumeMounts: 16 | - name: html 17 | mountPath: /usr/share/nginx/html 18 | readOnly: true 19 | ports: 20 | - containerPort: 80 21 | protocol: TCP 22 | 23 | volumes: 24 | - name: html 25 | emptyDir: 26 | medium: Memory 27 | -------------------------------------------------------------------------------- /workshop/05-volume/basic/mongodb_hostpath_pod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: mongodb 5 | spec: 6 | containers: 7 | - image: mongo 8 | name: mongodb 9 | volumeMounts: 10 | - name: mongodb-data 11 | mountPath: /data/db 12 | ports: 13 | - containerPort: 27017 14 | protocol: TCP 15 | volumes: 16 | - name: mongodb-data 17 | hostPath: 18 | path: /tmp/mongodb 19 | -------------------------------------------------------------------------------- /workshop/05-volume/basic/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | #### EmptyDir Volume #### 2 | 1. Create Pods with Volume EmptyDir (memory) 3 | $kubectl create -f empty_pod.yml 4 | $kubectl get pods -w 5 | 6 | 2. Forward a port from local machine to the Pods (Don't use in production) 7 | $kubectl port-forward tryempty 8080:80 8 | 9 | try localhost:8080 10 | 11 | 3. Delete pods 12 | $kubectl delete -f empty_pod.yml 13 | 14 | #### HostPath Volume #### 15 | 1. Create Pods with hostpath 16 | $kubectl create -f mongodb_hostpath_pod.yml 17 | $kubectl get pods -w 18 | 19 | 2. See your data file in /tmp/mongodb 20 | ls /tmp/mongodb 21 | -------------------------------------------------------------------------------- /workshop/05-volume/emptydir/demo_empty_dir.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: test-pd 5 | spec: 6 | containers: 7 | - image: k8s.gcr.io/test-webserver 8 | name: test-container 9 | volumeMounts: 10 | - mountPath: /cache 11 | name: cache-volume 12 | volumes: 13 | - name: cache-volume 14 | emptyDir: {} -------------------------------------------------------------------------------- /workshop/05-volume/emptydir/instruction.txt: -------------------------------------------------------------------------------- 1 | $kubectl create -f demo_empty_dir.yaml 2 | 3 | $kubectl get pod 4 | NAME READY STATUS RESTARTS AGE 5 | test-pd 1/1 Running 0 38s 6 | -------------------------------------------------------------------------------- /workshop/05-volume/hostPath/demo_hostpath.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: test-pd 5 | spec: 6 | containers: 7 | - image: k8s.gcr.io/test-webserver 8 | name: test-container 9 | volumeMounts: 10 | - mountPath: /test-pd 11 | name: test-volume 12 | volumes: 13 | - name: test-volume 14 | hostPath: 15 | # directory location on host 16 | path: /data 17 | # this field is optional 18 | type: Directory -------------------------------------------------------------------------------- /workshop/05-volume/nfs/nginx_deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nginx 9 | replicas: 2 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | spec: 15 | containers: 16 | - name: nginx 17 | image: nginx:1.8 18 | ports: 19 | - containerPort: 80 20 | volumeMounts: 21 | - name: try-nfs 22 | mountPath: "/usr/share/nginx/html" 23 | volumes: 24 | - name: try-nfs 25 | persistentVolumeClaim: 26 | claimName: pvc-nfs 27 | -------------------------------------------------------------------------------- /workshop/05-volume/nfs/nginx_service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nginx-web 5 | labels: 6 | name: nginx-web 7 | environment: development 8 | spec: 9 | selector: 10 | app: nginx 11 | type: NodePort 12 | ports: 13 | - port: 80 14 | name: http 15 | targetPort: 80 16 | protocol: TCP 17 | nodePort: 32500 18 | -------------------------------------------------------------------------------- /workshop/05-volume/nfs/pv.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: pv-nfs 5 | labels: 6 | name: pv-nfs 7 | environment: development 8 | spec: 9 | capacity: 10 | storage: 1Gi 11 | storageClassName: "" 12 | accessModes: 13 | - ReadWriteMany 14 | nfs: 15 | server: 10.148.0.2 16 | path: "/var/nfs/general" 17 | -------------------------------------------------------------------------------- /workshop/05-volume/nfs/pvc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-nfs 5 | labels: 6 | name: pvc-nfs 7 | environment: development 8 | spec: 9 | accessModes: 10 | - ReadWriteMany 11 | storageClassName: "" 12 | resources: 13 | requests: 14 | storage: 500Mi 15 | selector: 16 | matchLabels: 17 | name: pv-nfs 18 | environment: development 19 | -------------------------------------------------------------------------------- /workshop/05-volume/nfs/workshop_instruction.txt: -------------------------------------------------------------------------------- 1 | # 1. Create K8S Cluster 2 | $kubectl get node -o wide 3 | NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 4 | master Ready master 22m v1.11.0 10.148.0.2 Ubuntu 16.04.4 LTS 4.13.0-1019-gcp docker://18.3.1 5 | query Ready 3m v1.11.0 10.148.0.4 Ubuntu 16.04.4 LTS 4.13.0-1019-gcp docker://18.3.1 6 | 7 | # 2. Create NFS Server and clients 8 | $sudo apt-get update 9 | $sudo apt-get install nfs-kernel-server 10 | $sudo mkdir /var/nfs/general -p 11 | $sudo chmod 777 /var/nfs/general 12 | $sudo chown nobody:nogroup /var/nfs/general 13 | 14 | # Configuring the NFS Exports on the Host Server 15 | $sudo vi /etc/exports 16 | /var/nfs/general 10.148.0.0/24(rw,sync,no_root_squash,no_all_squash) 17 | 18 | # Restart NFS server 19 | $sudo exportfs -a 20 | $sudo systemctl restart nfs-kernel-server 21 | 22 | # Enable firewall 23 | $sudo ufw enable 24 | $sudo ufw status 25 | $sudo ufw allow from 10.148.0.4 to any port nfs 26 | 27 | # Mounting the directory on client 28 | $sudo apt-get update 29 | $sudo apt-get install nfs-common 30 | $sudo mkdir -p /nfs/general 31 | $sudo mount -t nfs 10.148.0.2::/var/nfs/general /nfs/general 32 | $df -kh 33 | 34 | Filesystem Size Used Avail Use% Mounted on 35 | udev 1.8G 0 1.8G 0% /dev 36 | tmpfs 370M 5.4M 364M 2% /run 37 | /dev/sda1 9.7G 3.0G 6.7G 31% / 38 | tmpfs 1.9G 0 1.9G 0% /dev/shm 39 | tmpfs 5.0M 0 5.0M 0% /run/lock 40 | tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup 41 | tmpfs 370M 0 370M 0% /run/user/1001 42 | 10.148.0.2:/var/nfs/general 9.7G 4.4G 5.3G 46% /nfs/general 43 | 44 | # Testing from master 45 | $touch /var/nfs/general/from_master.txt 46 | 47 | # Testing from worker 48 | $touch /nfs/general/from_query.txt 49 | 50 | 51 | # 3. Working PersistentVolume(PV) and PersistentVolumeClaim(PVC) 52 | $kubectl create -f pv.yml 53 | $kubectl create -f pvc.yml 54 | 55 | $kubectl get pv 56 | $kubectl describe pv/pv-nfs 57 | $kubectl get pvc 58 | $kubectl describe pvc/pvc-nfs 59 | 60 | # 4. Deploy application 61 | $kubectl create -f nginx_deployment.yml 62 | $kubectl create -f nginx_service.yml 63 | 64 | $kubectl get deployment 65 | $kubectl get svc 66 | $kubectl get pods 67 | 68 | # Create file /nfs/general/hello.html 69 | $vi /nfs/general/hello.html 70 |

Hello World

71 | 72 | # 5. Access to Pods to see files 73 | $kubectl exec -it sh 74 | 75 | > ls 76 | bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var 77 | > cd /usr/share/nginx/html 78 | > ls 79 | from_master.txt from_query.txt hello.html 80 | 81 | # 6. Delete all resources 82 | $kubectl delete -f nginx_deployment.yml 83 | $kubectl delete -f nginx_service.yml 84 | $kubectl delete -f pv.yml 85 | $kubectl delete -f pvc.yml 86 | 87 | 88 | Resources 89 | https://hub.docker.com/_/nginx/ 90 | https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nfs-mount-on-ubuntu-16-04 91 | https://github.com/janakiramm/wp-statefulset 92 | -------------------------------------------------------------------------------- /workshop/05-volume/persistent_volume/demo_pv.1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: webserver 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | run: webserver 10 | template: 11 | metadata: 12 | labels: 13 | run: webserver 14 | spec: 15 | containers: 16 | - image: k8s.gcr.io/test-webserver 17 | name: test-container 18 | volumeMounts: 19 | - mountPath: /test-pd 20 | name: test-volume 21 | volumes: 22 | - name: test-volume 23 | gcePersistentDisk: 24 | pdName: demo-pv 25 | fsType: ext4 26 | --- 27 | apiVersion: v1 28 | kind: Service 29 | metadata: 30 | name: webserver 31 | spec: 32 | ports: 33 | - protocol: TCP 34 | port: 80 35 | nodePort: 30088 36 | type: NodePort 37 | selector: 38 | run: webserver -------------------------------------------------------------------------------- /workshop/05-volume/persistent_volume/demo_pv.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: tomcat 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | run: tomcat 10 | template: 11 | metadata: 12 | labels: 13 | run: tomcat 14 | spec: 15 | containers: 16 | - image: tomcat 17 | name: tomcat 18 | ports: 19 | - containerPort: 8080 20 | volumeMounts: 21 | - mountPath: /usr/local/tomcat/logs 22 | name: tomcat-log 23 | volumes: 24 | - name: tomcat-log 25 | gcePersistentDisk: 26 | pdName: demo-pv 27 | fsType: ext4 28 | --- 29 | apiVersion: v1 30 | kind: Service 31 | metadata: 32 | name: tomcat 33 | spec: 34 | ports: 35 | - protocol: TCP 36 | port: 8080 37 | nodePort: 30089 38 | type: NodePort 39 | selector: 40 | run: tomcat -------------------------------------------------------------------------------- /workshop/05-volume/persistent_volume_claim/instruction.txt: -------------------------------------------------------------------------------- 1 | $kubectl create -f pv_01.yaml 2 | $kubectl create -f pvc_01.yaml 3 | $kubectl create -f tomcat_pvc_01.yaml 4 | 5 | $kubectl get pv 6 | $kubectl get pvc 7 | $kubectl get pod 8 | $kubectl get service 9 | -------------------------------------------------------------------------------- /workshop/05-volume/persistent_volume_claim/pv_01.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "v1" 2 | kind: "PersistentVolume" 3 | metadata: 4 | name: pv-1 5 | spec: 6 | storageClassName: "my-10g-pv-1" 7 | capacity: 8 | storage: "10Gi" 9 | accessModes: 10 | - "ReadWriteOnce" 11 | gcePersistentDisk: 12 | fsType: "ext4" 13 | pdName: "demo-pv" -------------------------------------------------------------------------------- /workshop/05-volume/persistent_volume_claim/pvc_01.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-1 5 | spec: 6 | storageClassName: "my-10g-pv-1" 7 | accessModes: 8 | - ReadWriteOnce 9 | resources: 10 | requests: 11 | storage: 10Gi -------------------------------------------------------------------------------- /workshop/05-volume/persistent_volume_claim/tomcat_pvc_01.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: tomcat 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | run: tomcat 10 | template: 11 | metadata: 12 | labels: 13 | run: tomcat 14 | spec: 15 | containers: 16 | - image: tomcat 17 | name: tomcat 18 | ports: 19 | - containerPort: 8080 20 | volumeMounts: 21 | - mountPath: /usr/local/tomcat/logs 22 | name: tomcat-log 23 | volumes: 24 | - name: tomcat-log 25 | persistentVolumeClaim: 26 | claimName: "pvc-1" 27 | --- 28 | apiVersion: v1 29 | kind: Service 30 | metadata: 31 | name: tomcat 32 | spec: 33 | ports: 34 | - protocol: TCP 35 | port: 8080 36 | nodePort: 30088 37 | type: NodePort 38 | selector: 39 | run: tomcat -------------------------------------------------------------------------------- /workshop/05-volume/storage_class/pvc_gcp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-gcp-02 5 | spec: 6 | storageClassName: "gcp-sc" 7 | accessModes: 8 | - ReadWriteOnce 9 | resources: 10 | requests: 11 | storage: 5Gi -------------------------------------------------------------------------------- /workshop/05-volume/storage_class/sc_gcp.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: gcp-sc 5 | provisioner: kubernetes.io/gce-pd 6 | parameters: 7 | type: pd-standard -------------------------------------------------------------------------------- /workshop/05-volume/storage_class/tomcat_pvc_01.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: tomcat 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | run: tomcat 10 | template: 11 | metadata: 12 | labels: 13 | run: tomcat 14 | spec: 15 | containers: 16 | - image: tomcat 17 | name: tomcat 18 | ports: 19 | - containerPort: 8080 20 | volumeMounts: 21 | - mountPath: /usr/local/tomcat/logs 22 | name: tomcat-log 23 | volumes: 24 | - name: tomcat-log 25 | persistentVolumeClaim: 26 | claimName: "pvc-gcp-02" 27 | --- 28 | apiVersion: v1 29 | kind: Service 30 | metadata: 31 | name: tomcat 32 | spec: 33 | ports: 34 | - protocol: TCP 35 | port: 8080 36 | nodePort: 30088 37 | type: NodePort 38 | selector: 39 | run: tomcat -------------------------------------------------------------------------------- /workshop/configmap/better/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: better-config 5 | data: 6 | web.properties: | 7 | endpoint=somkiat.cc 8 | port=99999 -------------------------------------------------------------------------------- /workshop/configmap/better/instruction.txt: -------------------------------------------------------------------------------- 1 | Deploy Pod and ConfigMap 2 | $kubectl create -f . 3 | $kubectl get po 4 | NAME READY STATUS RESTARTS AGE 5 | configmap-volume 1/1 Running 0 28s 6 | 7 | Access to Pod 8 | $kubectl exec -it configmap-volume sh 9 | sh#cat /src/app/config/web.properties 10 | endpoint=somkiat.cc 11 | port=80 12 | 13 | sh#exit 14 | 15 | Edit config.yaml and run 16 | $kubectl apply -f config.yaml 17 | 18 | Access to Pod again (Not update in realtime, waiting time > 1 minute) 19 | $kubectl exec -it configmap-volume sh 20 | sh#cat /src/app/config/web.properties 21 | endpoint=somkiat.cc 22 | port=8080 23 | -------------------------------------------------------------------------------- /workshop/configmap/better/pod-with-volume-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: configmap-volume 5 | spec: 6 | containers: 7 | - name: configmap 8 | image: centos 9 | command: ["/bin/sh", "-c", "while : ;do cat /src/app/config/web.properties; sleep 10; done"] 10 | volumeMounts: 11 | - name: config-volume 12 | mountPath: /src/app/config 13 | volumes: 14 | - name: config-volume 15 | configMap: 16 | name: better-config -------------------------------------------------------------------------------- /workshop/configmap/code/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10.15.1-alpine 2 | WORKDIR /src 3 | EXPOSE 3000 4 | ENV LANGUAGE English 5 | ENV API_KEY 123-456-789 6 | COPY . /src 7 | CMD ["node", "index.js"] -------------------------------------------------------------------------------- /workshop/configmap/code/index.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var server = http.createServer(function (request, response) { 3 | const language = process.env.LANGUAGE; 4 | const API_KEY = process.env.API_KEY; 5 | response.write(`Language: ${language}\n`); 6 | response.write(`API Key: ${API_KEY}\n`); 7 | response.end(`\n`); 8 | }); 9 | process.on('SIGINT', function() { 10 | console.log("Exit !!!"); 11 | process.exit(); 12 | }); 13 | server.listen(3000); -------------------------------------------------------------------------------- /workshop/configmap/config_01.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: config-01 5 | data: 6 | LANGUAGE: Lang 01 7 | API_KEY: V 01 -------------------------------------------------------------------------------- /workshop/configmap/config_02.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: config-02 5 | data: 6 | LANGUAGE: Lang 02 7 | API_KEY: V 02 -------------------------------------------------------------------------------- /workshop/configmap/deployment_01.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: envtest 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | name: envtest 10 | template: 11 | metadata: 12 | labels: 13 | name: envtest 14 | spec: 15 | containers: 16 | - name: demo 17 | image: somkiat/demo_node:1.0 18 | ports: 19 | - containerPort: 3000 20 | hostPort: 80 21 | env: 22 | - name: LANGUAGE 23 | value: "English" 24 | - name: API_KEY 25 | value: "123-456-789" -------------------------------------------------------------------------------- /workshop/configmap/deployment_02.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: envtest 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | name: envtest 10 | template: 11 | metadata: 12 | labels: 13 | name: envtest 14 | spec: 15 | containers: 16 | - name: demo 17 | image: somkiat/demo_node:1.0 18 | ports: 19 | - containerPort: 3000 20 | hostPort: 80 21 | env: 22 | - name: LANGUAGE 23 | valueFrom: 24 | configMapKeyRef: 25 | name: language 26 | key: LANGUAGE 27 | - name: API_KEY 28 | valueFrom: 29 | secretKeyRef: 30 | name: apikey 31 | key: API_KEY -------------------------------------------------------------------------------- /workshop/configmap/deployment_03.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: envtest 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | name: envtest 10 | template: 11 | metadata: 12 | labels: 13 | name: envtest 14 | spec: 15 | containers: 16 | - name: demo 17 | image: somkiat/demo_node:1.0 18 | ports: 19 | - containerPort: 3000 20 | hostPort: 80 21 | envFrom: 22 | - configMapRef: 23 | name: config-01 -------------------------------------------------------------------------------- /workshop/configmap/instruction.txt: -------------------------------------------------------------------------------- 1 | Step 1 :: Run with simple way 2 | 3 | For Linux/Mac 4 | $cd code 5 | $export LANGUAGE=1 6 | $export API_KEY=2 7 | $node index.js 8 | 9 | For Windows 10 | $cd code 11 | $set LANGUAGE=English 12 | $set API_KEY=123-456-789 13 | $node index.js 14 | 15 | Open url=http://localhost:3000 in your browser 16 | 17 | Step 2 :: Run with Docker way 18 | 19 | $cd code 20 | $docker image build -t demo:1.0 . 21 | $docker container run --rm -p 3000:3000 demo:1.0 22 | 23 | Open url=http://localhost:3000 in your browser 24 | 25 | If you want to change value of environment variables 26 | 27 | $docker container run --rm -p 3000:3000 -e LANGUAGE=Thai demo:1.0 28 | 29 | Step 3 :: Run with Kubernetes way by using Environment variable 30 | 31 | $kubectl create -f deployment_01.yaml 32 | $kubectl get pod 33 | $curl http://:80 34 | 35 | Step 4 :: Run with Kubernetes way by using ConfigMap and Secret 36 | 37 | API_KEY is a secret value 38 | LANGUAGE is a configuration value 39 | 40 | Create secret value with Kuberneter's Secret (BASE64-> Encode not Encrypt !!) 41 | $kubectl create secret generic apikey --from-literal=API_KEY=123–456-789 42 | $kubectl get secret 43 | 44 | Create config map 45 | $kubectl create configmap language --from-literal=LANGUAGE=English 46 | $kubectl get configmap 47 | 48 | Deploy Pods 49 | $kubectl create -f deployment_02.yaml 50 | $kubectl get po -w 51 | $kubectl get po -o wide 52 | $kubectl get node -o wide 53 | 54 | $curl http://:80 55 | 56 | Update configmap and secret 57 | $kubectl create configmap language --from-literal=LANGUAGE=Thai -o yaml --dry-run | kubectl replace -f - 58 | kubectl create secret generic apikey --from-literal=API_KEY=098765 -o yaml --dry-run | kubectl replace -f - 59 | 60 | BUT Environment environment in Pod not change !!! (Caching data on startup...) 61 | Try to delete pod !! 62 | $kubectl delete pod/ 63 | 64 | $kubectl get po -w 65 | $kubectl get po -o wide 66 | $kubectl get node -o wide 67 | $curl http://:80 68 | 69 | Better solution ? 70 | 71 | Delete all resources 72 | $kubectl delete -f deployment_01.yaml 73 | $kubectl delete -f deployment_02.yaml 74 | 75 | Create configmap resource 76 | $kubectl create -f config_01.yaml 77 | $kubectl get configmap 78 | 79 | Deploy new Pod 80 | $kubectl create -f deployment_03.yaml 81 | $curl http://:80 82 | 83 | Update configuration ... 84 | $kubectl create -f config_02.yaml 85 | 86 | Edit in file deployment_03.yaml with name: config-02 and save then 87 | $kubectl apply -f deployment_03.yaml 88 | $kubectl get po -w 89 | $kubectl get po -o wide 90 | $kubectl get node -o wide 91 | $curl http://:80 -------------------------------------------------------------------------------- /workshop/healthcheck/hello_deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: hello 5 | spec: 6 | replicas: 3 7 | template: 8 | metadata: 9 | labels: 10 | app: web 11 | spec: 12 | containers: 13 | - name: hello 14 | image: somkiat/hello:v2 15 | ports: 16 | - name: hello-port 17 | containerPort: 8080 18 | livenessProbe: 19 | httpGet: 20 | path: / 21 | port: 8888 22 | initialDelaySeconds: 15 23 | timeoutSeconds: 30 24 | -------------------------------------------------------------------------------- /workshop/healthcheck/hello_deployment_readiness.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: hello 5 | spec: 6 | replicas: 3 7 | template: 8 | metadata: 9 | labels: 10 | app: web 11 | spec: 12 | containers: 13 | - name: hello 14 | image: somkiat/hello:v2 15 | ports: 16 | - name: hello-port 17 | containerPort: 8080 18 | livenessProbe: 19 | httpGet: 20 | path: / 21 | port: 8080 22 | initialDelaySeconds: 15 23 | timeoutSeconds: 30 24 | readinessProbe: 25 | httpGet: 26 | path: / 27 | port: 8888 28 | initialDelaySeconds: 15 29 | timeoutSeconds: 30 30 | -------------------------------------------------------------------------------- /workshop/jobs/cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1beta1 2 | kind: CronJob 3 | metadata: 4 | name: hello 5 | spec: 6 | schedule: "*/1 * * * *" 7 | jobTemplate: 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: my-cronjob 13 | image: busybox 14 | args: 15 | - /bin/sh 16 | - -c 17 | - echo This commmand runs every minute 18 | restartPolicy: OnFailure 19 | -------------------------------------------------------------------------------- /workshop/jobs/instruction.txt: -------------------------------------------------------------------------------- 1 | # Crate CronJob 2 | $kubectl create -f cronjob.yaml 3 | $kubectl get cronjob 4 | $kubectl get jobs 5 | 6 | # Create Jobs 7 | $kubectl create -f job.yaml 8 | $kubectl get jobs 9 | 10 | # References 11 | https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/ 12 | -------------------------------------------------------------------------------- /workshop/jobs/job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: pi 5 | spec: 6 | template: 7 | metadata: 8 | name: pi 9 | spec: 10 | containers: 11 | - name: pi 12 | image: perl 13 | command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] 14 | restartPolicy: Never 15 | -------------------------------------------------------------------------------- /workshop/logging/basic_pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: counter 5 | spec: 6 | containers: 7 | - name: count 8 | image: busybox 9 | args: [/bin/sh, -c, 10 | 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done'] 11 | -------------------------------------------------------------------------------- /workshop/logging/instruction.txt: -------------------------------------------------------------------------------- 1 | ### Write log of each Pods to stdout ### 2 | 1. Create basic of logging Pods (Write log to stdout) 3 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/workshop/logging/basic_pod.yaml 4 | $kubectl get pods 5 | 6 | 2. See log message of Pods with stream 7 | $kubectl logs -f po/counter 8 | $kubectl logs -f po/counter -c count 9 | 10 | # Logging with Papertrail (https://papertrailapp.com/) 11 | 12 | $kubectl create secret generic papertrail-destination --from-literal=papertrail-destination=syslog://logs4.papertrailapp.com:32397 13 | $kubectl create -f https://help.papertrailapp.com/assets/files/papertrail-logspout-daemonset.yml 14 | 15 | 16 | # Logging with EFK (Elasticsearch + Fluentd + Kibana) 17 | # https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch 18 | 1. Create namespace 19 | $kubectl create namespace demologging 20 | $kubectl get ns 21 | 22 | 2. Enable EFK add-on 23 | $minikube addons enable efk 24 | $kubectl get pods --all-namespaces 25 | kube-system elasticsearch-logging-fx8w2 1/1 Running 0 5m 26 | kube-system fluentd-es-f986j 1/1 Running 0 5m 27 | kube-system kibana-logging-7jvgw 1/1 Running 0 5m 28 | 29 | See log from kibana 30 | $kubectl logs -f kibana-logging-7jvgw --namespace=kube-system 31 | 32 | Access kibana 33 | $minikube service kibana-logging --namespace=kube-system 34 | -------------------------------------------------------------------------------- /workshop/namespace-label/instruction.txt: -------------------------------------------------------------------------------- 1 | # Get all namespce 2 | $kubectl get namespce 3 | $kubectl get ns 4 | 5 | # Create resource with namespace 6 | $kubectl --namespace=dev run nginx --image=nginx 7 | $kubectl --namespace=dev get pods 8 | 9 | 10 | # Resources 11 | https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ 12 | -------------------------------------------------------------------------------- /workshop/note20180702/kubernetes-dashboard.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Configuration to deploy release version of the Dashboard UI compatible with 16 | # Kubernetes 1.8. 17 | # 18 | # Example usage: kubectl create -f 19 | 20 | # ------------------- Dashboard Secret ------------------- # 21 | 22 | apiVersion: v1 23 | kind: Secret 24 | metadata: 25 | labels: 26 | k8s-app: kubernetes-dashboard 27 | name: kubernetes-dashboard-certs 28 | namespace: kube-system 29 | type: Opaque 30 | 31 | --- 32 | # ------------------- Dashboard Service Account ------------------- # 33 | 34 | apiVersion: v1 35 | kind: ServiceAccount 36 | metadata: 37 | labels: 38 | k8s-app: kubernetes-dashboard 39 | name: kubernetes-dashboard 40 | namespace: kube-system 41 | 42 | --- 43 | # ------------------- Dashboard Role & Role Binding ------------------- # 44 | 45 | kind: Role 46 | apiVersion: rbac.authorization.k8s.io/v1 47 | metadata: 48 | name: kubernetes-dashboard-minimal 49 | namespace: kube-system 50 | rules: 51 | # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret. 52 | - apiGroups: [""] 53 | resources: ["secrets"] 54 | verbs: ["create"] 55 | # Allow Dashboard to create 'kubernetes-dashboard-settings' config map. 56 | - apiGroups: [""] 57 | resources: ["configmaps"] 58 | verbs: ["create"] 59 | # Allow Dashboard to get, update and delete Dashboard exclusive secrets. 60 | - apiGroups: [""] 61 | resources: ["secrets"] 62 | resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"] 63 | verbs: ["get", "update", "delete"] 64 | # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. 65 | - apiGroups: [""] 66 | resources: ["configmaps"] 67 | resourceNames: ["kubernetes-dashboard-settings"] 68 | verbs: ["get", "update"] 69 | # Allow Dashboard to get metrics from heapster. 70 | - apiGroups: [""] 71 | resources: ["services"] 72 | resourceNames: ["heapster"] 73 | verbs: ["proxy"] 74 | - apiGroups: [""] 75 | resources: ["services/proxy"] 76 | resourceNames: ["heapster", "http:heapster:", "https:heapster:"] 77 | verbs: ["get"] 78 | 79 | --- 80 | apiVersion: rbac.authorization.k8s.io/v1 81 | kind: RoleBinding 82 | metadata: 83 | name: kubernetes-dashboard-minimal 84 | namespace: kube-system 85 | roleRef: 86 | apiGroup: rbac.authorization.k8s.io 87 | kind: Role 88 | name: kubernetes-dashboard-minimal 89 | subjects: 90 | - kind: ServiceAccount 91 | name: kubernetes-dashboard 92 | namespace: kube-system 93 | 94 | --- 95 | # ------------------- Dashboard Deployment ------------------- # 96 | 97 | kind: Deployment 98 | apiVersion: apps/v1beta2 99 | metadata: 100 | labels: 101 | k8s-app: kubernetes-dashboard 102 | name: kubernetes-dashboard 103 | namespace: kube-system 104 | spec: 105 | replicas: 1 106 | revisionHistoryLimit: 10 107 | selector: 108 | matchLabels: 109 | k8s-app: kubernetes-dashboard 110 | template: 111 | metadata: 112 | labels: 113 | k8s-app: kubernetes-dashboard 114 | spec: 115 | containers: 116 | - name: kubernetes-dashboard 117 | image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3 118 | ports: 119 | - containerPort: 8443 120 | protocol: TCP 121 | args: 122 | - --auto-generate-certificates 123 | # Uncomment the following line to manually specify Kubernetes API server Host 124 | # If not specified, Dashboard will attempt to auto discover the API server and connect 125 | # to it. Uncomment only if the default does not work. 126 | # - --apiserver-host=http://my-address:port 127 | volumeMounts: 128 | - name: kubernetes-dashboard-certs 129 | mountPath: /certs 130 | # Create on-disk volume to store exec logs 131 | - mountPath: /tmp 132 | name: tmp-volume 133 | livenessProbe: 134 | httpGet: 135 | scheme: HTTPS 136 | path: / 137 | port: 8443 138 | initialDelaySeconds: 30 139 | timeoutSeconds: 30 140 | volumes: 141 | - name: kubernetes-dashboard-certs 142 | secret: 143 | secretName: kubernetes-dashboard-certs 144 | - name: tmp-volume 145 | emptyDir: {} 146 | serviceAccountName: kubernetes-dashboard 147 | # Comment the following tolerations if Dashboard must not be deployed on master 148 | tolerations: 149 | - key: node-role.kubernetes.io/master 150 | effect: NoSchedule 151 | 152 | --- 153 | # ------------------- Dashboard Service ------------------- # 154 | 155 | kind: Service 156 | apiVersion: v1 157 | metadata: 158 | labels: 159 | k8s-app: kubernetes-dashboard 160 | name: kubernetes-dashboard 161 | namespace: kube-system 162 | spec: 163 | type: NodePort 164 | ports: 165 | - port: 443 166 | targetPort: 8443 167 | selector: 168 | k8s-app: kubernetes-dashboard 169 | -------------------------------------------------------------------------------- /workshop/note20180702/note.txt: -------------------------------------------------------------------------------- 1 | https://github.com/up1/course-kubernetes-in-practice 2 | 3 | set http_proxy=pxc.set:80 4 | set https_proxy=pxc.set:80 5 | minukube start 6 | 7 | 8 | 9 | # Using Play with K8S 10 | # https://labs.play-with-k8s.com/ 11 | 12 | 1. Initializes cluster master node: 13 | 14 | kubeadm init --apiserver-advertise-address $(hostname -i) 15 | 16 | To start using your cluster, you need to run (as a regular user) 17 | mkdir -p $HOME/.kube 18 | cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 19 | chown $(id -u):$(id -g) $HOME/.kube/config 20 | 21 | 22 | 2. Initialize cluster networking: 23 | 24 | kubectl apply -n kube-system -f \ 25 | "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 |tr -d '\n')" 26 | 27 | 3. kubectl get node 28 | NAME STATUS ROLES AGE VERSION 29 | node1 Ready master 6m v1.10.2 30 | 31 | 4. Worker node join master 32 | kubeadm join --token 57b17b.ab262ec06e10e59d 192.168.0.8:6443 --discovery-token-ca-cert-hash sha256:4a5a0f0a573dc501f24c8a63c638c10343e47bcc57c423fc484e4334d2e4a043 33 | 34 | 5. Using kubectl 35 | kubectl get all --namespace=kube-system 36 | docker container ps 37 | 38 | 6. try with 01-hello/workshop_instruction.txt 39 | Concept iof Pods, Replication Controller and Service 40 | 41 | 42 | 7. Get DNS name of pods 43 | $kubectl get pod -o wide 44 | $kubectl exec hello-flhbv cat /etc/resolv.conf 45 | https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/ 46 | https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#services 47 | 48 | 8. Cluster information 49 | $kubectl cluster-info 50 | $kubectl config view 51 | https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-services/ 52 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/golang-http-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.6 2 | RUN mkdir /app 3 | ADD . /app/ 4 | WORKDIR /app 5 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . 6 | CMD ["/app/main"] 7 | 8 | EXPOSE 80 9 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/golang-http-server/Dockerfile-release: -------------------------------------------------------------------------------- 1 | FROM alpine:3.2 2 | 3 | RUN apk --update add curl 4 | EXPOSE 80 5 | CMD ["/app"] 6 | 7 | COPY app / 8 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/golang-http-server/Makefile: -------------------------------------------------------------------------------- 1 | NAME = somkiat/http-server-go 2 | INSTANCE = http-server-go 3 | 4 | .PHONY: default build copy debug clean push 5 | 6 | default: build 7 | 8 | build: 9 | docker build -t $(NAME)-dev . 10 | 11 | copy: 12 | docker create --name $(INSTANCE) $(NAME)-dev 13 | docker cp $(INSTANCE):/app/main $(shell pwd)/app 14 | docker rm $(INSTANCE) 15 | 16 | release: 17 | docker build -t $(NAME) -f Dockerfile-release . 18 | docker tag $(NAME):latest $(NAME):health 19 | 20 | clean: 21 | docker rm $(INSTANCE) 22 | 23 | debug: 24 | docker run --rm -it --name $(INSTANCE) $(NAME)-dev /bin/bash 25 | 26 | run: 27 | docker run --rm -p 80:80 --name $(INSTANCE) $(NAME) 28 | 29 | dev: 30 | docker run -it --rm -p 80:80 -w /go/src/github.com/$(NAME) -v $(shell pwd)/vendor/github.com/:/go/src/github.com/ -v $(shell pwd):/go/src/github.com/$(NAME) golang:1.6 31 | 32 | push: 33 | docker push $(NAME):latest 34 | docker push $(NAME):v1 35 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/golang-http-server/app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | ) 8 | 9 | var isHealthy bool 10 | 11 | func handler(w http.ResponseWriter, r *http.Request) { 12 | var name, _ = os.Hostname() 13 | 14 | if(isHealthy) { 15 | fmt.Fprintf(w, "

A healthy request was processed by host: %s

\n", name) 16 | } else { 17 | w.WriteHeader(500) 18 | fmt.Fprintf(w, "

A unhealthy request was processed by host: %s

\n", name) 19 | } 20 | } 21 | 22 | func healthy(w http.ResponseWriter, r *http.Request) { 23 | isHealthy = true 24 | } 25 | 26 | func unhealthy(w http.ResponseWriter, r *http.Request) { 27 | isHealthy = false 28 | } 29 | 30 | func main() { 31 | fmt.Fprintf(os.Stdout, "Web Server started. Listening on 0.0.0.0:80\n") 32 | isHealthy = true 33 | http.HandleFunc("/", handler) 34 | http.HandleFunc("/healthy", healthy) 35 | http.HandleFunc("/unhealthy", unhealthy) 36 | http.ListenAndServe(":80", nil) 37 | } 38 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/golang-http-server/instruction.txt: -------------------------------------------------------------------------------- 1 | # Create Pods with liveness 2 | $kubectl create -f https://raw.githubusercontent.com/up1/course-kubernetes-in-practice/master/workshop/readiness-and-liveness/golang-http-server/liveness.yaml 3 | $kubectl get pods -o wide 4 | 5 | # Try to unhealthy Pods 6 | $kubectl exec demo-liveness-http -- /usr/bin/curl -s localhost/unhealthy 7 | $kubectl get pods -o wide 8 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/golang-http-server/liveness.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | test: liveness 6 | name: demo-liveness-http 7 | spec: 8 | containers: 9 | - name: demo-with-go 10 | image: somkiat/http-server-go-dev 11 | livenessProbe: 12 | httpGet: 13 | path: / 14 | port: 80 15 | initialDelaySeconds: 1 16 | timeoutSeconds: 1 17 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/liveness_command.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | test: liveness 6 | name: liveness-exec 7 | spec: 8 | containers: 9 | - name: liveness 10 | image: k8s.gcr.io/busybox 11 | args: 12 | - /bin/sh 13 | - -c 14 | - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 15 | livenessProbe: 16 | exec: 17 | command: 18 | - cat 19 | - /tmp/healthy 20 | initialDelaySeconds: 5 21 | periodSeconds: 5 22 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/liveness_http.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | test: liveness 6 | name: liveness-http 7 | spec: 8 | containers: 9 | - name: liveness 10 | image: k8s.gcr.io/liveness 11 | args: 12 | - /server 13 | livenessProbe: 14 | httpGet: 15 | path: /healthz 16 | port: 8080 17 | httpHeaders: 18 | - name: X-Custom-Header 19 | value: Awesome 20 | initialDelaySeconds: 3 21 | periodSeconds: 3 22 | -------------------------------------------------------------------------------- /workshop/readiness-and-liveness/liveness_tcp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: goproxy 5 | labels: 6 | app: goproxy 7 | spec: 8 | containers: 9 | - name: goproxy 10 | image: k8s.gcr.io/goproxy:0.1 11 | ports: 12 | - containerPort: 8080 13 | readinessProbe: 14 | tcpSocket: 15 | port: 8080 16 | initialDelaySeconds: 5 17 | periodSeconds: 10 18 | livenessProbe: 19 | tcpSocket: 20 | port: 8080 21 | initialDelaySeconds: 15 22 | periodSeconds: 20 23 | 24 | -------------------------------------------------------------------------------- /workshop/setup.txt: -------------------------------------------------------------------------------- 1 | $gcloud compute --project "composed-future-200415" ssh --zone "asia-south1-a" "gitlab" 2 | 3 | 4 | # Install kubectl + minikube + kubeadm 5 | https://kubernetes.io/docs/setup/ 6 | 7 | $sudo apt-get install virtualbox 8 | $curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/ 9 | $curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.27.0/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/ 10 | 11 | # Start minikube 12 | $minikube get-k8s-versions 13 | $minikube start 14 | $minikube start --kubernetes-version=v1.10.0 15 | $kubectl version 16 | $kubectl cluster-info 17 | $minikube --help 18 | --------------------------------------------------------------------------------