├── lab
├── generate-html.sh
├── images
│ ├── build.png
│ ├── pod.png
│ ├── k8slogo.png
│ ├── openshift.png
│ ├── app-diagram.png
│ ├── app-screenshot.png
│ ├── helloworldmsa.png
│ ├── rolling-update.png
│ └── vagrant-windows-git.png
├── pull-images.sh
├── includes
│ └── tip.adoc
├── feedback.adoc
├── docker-image-minishift.adoc
├── configuring-application.adoc
├── app-application-source.adoc
├── references.adoc
├── app-frontend-service.adoc
├── graceful-shutdown.adoc
├── configuring-envvars.adoc
├── troubleshooting.adoc
├── app-deploy-mysql-and-service.adoc
├── configuring-argument.adoc
├── rolling-update.adoc
├── setup-environment.adoc
├── autoscaling.adoc
├── readme.adoc
├── preface.adoc
├── scaling.adoc
├── app-frontend-deployment.adoc
├── health-checks.adoc
├── app-deploy-microservices-networking.adoc
├── external-access.adoc
├── app-deploy-microservices.adoc
├── configuring-configmap.adoc
├── managing-credentials.adoc
├── extra.adoc
└── openshift.adoc
├── helloworld-service
├── config.json
├── builddocker.sh
├── Readme.md
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── redhat
│ │ └── developers
│ │ └── helloworld
│ │ ├── HelloworldVerticle.java
│ │ └── ApplicationConfiguration.java
└── pom.xml
├── frontend
├── builddocker.sh
├── package.json
├── Dockerfile
├── scripts
│ └── page.js
├── frontend.js
└── index.html
├── guestbook-service
├── builddocker.sh
├── src
│ └── main
│ │ ├── resources
│ │ ├── META-INF
│ │ │ ├── apache-deltaspike.properties
│ │ │ ├── beans.xml
│ │ │ └── persistence.xml
│ │ ├── modules
│ │ │ └── com
│ │ │ │ └── mysql
│ │ │ │ └── main
│ │ │ │ └── module.xml
│ │ └── import.sql
│ │ └── java
│ │ └── com
│ │ └── redhat
│ │ └── developers
│ │ └── guestbook
│ │ ├── rest
│ │ ├── CorsFilter.java
│ │ ├── JaxRsActivator.java
│ │ ├── MessageResource.java
│ │ └── BadwordFilter.java
│ │ ├── data
│ │ ├── MessageRepository.java
│ │ └── Message.java
│ │ ├── Resources.java
│ │ └── Main.java
├── Readme.md
├── Dockerfile
└── pom.xml
├── openshift
└── setup-pv.sh
├── README.md
├── kubernetes
├── mysql-pv.yaml
├── mysql-pvc.yaml
├── guestbookservice-service.yaml
├── helloworldservice-service.yaml
├── frontend-service.yaml
├── mysql-service.yaml
├── frontend-deployment.yaml
├── guestbookservice-deployment.yaml
├── helloworldservice-deployment.yaml
└── mysql-deployment.yaml
└── LICENSE
/lab/generate-html.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | asciidoctor readme.adoc
4 | open readme.html
--------------------------------------------------------------------------------
/helloworld-service/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "GREETING": "Hello {name} from {hostname} from ConfigMap"
3 | }
4 |
--------------------------------------------------------------------------------
/lab/images/build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/build.png
--------------------------------------------------------------------------------
/lab/images/pod.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/pod.png
--------------------------------------------------------------------------------
/lab/images/k8slogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/k8slogo.png
--------------------------------------------------------------------------------
/lab/images/openshift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/openshift.png
--------------------------------------------------------------------------------
/lab/images/app-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/app-diagram.png
--------------------------------------------------------------------------------
/lab/images/app-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/app-screenshot.png
--------------------------------------------------------------------------------
/lab/images/helloworldmsa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/helloworldmsa.png
--------------------------------------------------------------------------------
/lab/images/rolling-update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/rolling-update.png
--------------------------------------------------------------------------------
/frontend/builddocker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | name='rafabene/microservices-frontend:1.0'
3 | docker build -t $name .
4 | echo "Image $name built"
--------------------------------------------------------------------------------
/lab/images/vagrant-windows-git.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer-demos/kubernetes-lab/HEAD/lab/images/vagrant-windows-git.png
--------------------------------------------------------------------------------
/guestbook-service/builddocker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | name='rafabene/microservices-guestbook:1.0'
3 | mvn clean package; docker build -t $name .
4 | echo "Image $name built"
--------------------------------------------------------------------------------
/helloworld-service/builddocker.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | name='rafabene/microservices-helloworld-vertx:1.0'
3 | mvn clean package; docker build -t $name .
4 | echo "Image $name built"
--------------------------------------------------------------------------------
/guestbook-service/src/main/resources/META-INF/apache-deltaspike.properties:
--------------------------------------------------------------------------------
1 | globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy
2 |
--------------------------------------------------------------------------------
/lab/pull-images.sh:
--------------------------------------------------------------------------------
1 | docker pull rafabene/microservices-frontend:1.0
2 | docker pull rafabene/microservices-helloworld-vertx:1.0
3 | docker pull rafabene/microservices-guestbook:1.0
4 | docker pull openshift3/nodejs-010-rhel7
5 | docker pull openshift/mysql-56-centos7
6 | docker pull openshift/nodejs-010-centos7
7 | docker pull openshift/origin-sti-builder:v1.4.1
8 |
--------------------------------------------------------------------------------
/helloworld-service/Readme.md:
--------------------------------------------------------------------------------
1 | # Helloworld-service
2 |
3 | Build and Deploy helloworld-service locally
4 | ------------------------------------------
5 |
6 | 1. Open a command prompt and navigate to the root directory of this microservice.
7 | 2. Type this command to build and execute the service:
8 |
9 | mvn clean compile exec:java
10 |
11 | 3. The application will be running at the following URL:
--------------------------------------------------------------------------------
/openshift/setup-pv.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | for i in {1..1}; do
3 | echo "Creating Google disk $i";
4 | gcloud compute disks create pd-disk-$i --size 1GB --type=pd-ssd;
5 | cat <
--------------------------------------------------------------------------------
/guestbook-service/src/main/resources/modules/com/mysql/main/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/rest/CorsFilter.java:
--------------------------------------------------------------------------------
1 | package com.redhat.developers.guestbook.rest;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.ws.rs.container.ContainerRequestContext;
6 | import javax.ws.rs.container.ContainerResponseContext;
7 | import javax.ws.rs.container.ContainerResponseFilter;
8 | import javax.ws.rs.ext.Provider;
9 |
10 | @Provider
11 | public class CorsFilter implements ContainerResponseFilter {
12 |
13 | @Override
14 | public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
15 | responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "1.0.0",
4 | "description": "Frontend for Greeting and Helloworld microservices",
5 | "main": "frontend.js",
6 | "scripts": {
7 | "start": "node frontend.js"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/redhat-developer-demos/kubernetes-lab.git"
12 | },
13 | "author": "Red Hat Developers",
14 | "license": "Apache-2.0",
15 | "bugs": {
16 | "url": "https://github.com/redhat-developer-demos/kubernetes-lab/issues"
17 | },
18 | "homepage": "https://github.com/redhat-developer-demos/kubernetes-lab#readme",
19 | "dependencies": {
20 | "body-parser": "^1.15.1",
21 | "bootstrap": "~3.3.5",
22 | "express": "^4.13.4",
23 | "jquery": "~3.0.0",
24 | "patternfly": "^3.3.3",
25 | "request": "^2.72.0"
26 | },
27 | "optionalDependencies": {
28 | "phantomjs": "~1.9"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lab/includes/tip.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | [TIP]
17 | ====
18 | HINT 1: Type *'i'* to enter in edit mode
19 |
20 | HINT 2: Type *':wq'* to exit from vi
21 | ====
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Lab
2 |
3 | This lab is inspired in [Google's Kubernetes lab](http://bit.ly/k8s-lab) by [Ray Tsang](https://twitter.com/saturnism). However, this version uses [Red Hat's CDK](http://developers.redhat.com/products/cdk/overview/) - Container Development Kit, allowing users to try the lab localy, and also try the same lab in [OpenShift](https://www.openshift.com/).
4 |
5 | Furthermore, the microservices use: [WildFly Swarm](http://wildfly-swarm.io/) - A Java [microprofile](http://microprofile.io/) server, and [Vert.x](http://vertx.io/) - A a tool-kit for building reactive applications on the JVM.
6 |
7 | - [Lab Sources](lab/)
8 | - [Frontend source code](frontend/)
9 | - [Helloworld Microservice - implemented using Vert.x](helloworld-service/)
10 | - [Guestbook Microservice - implemented using WildFly Swarm](guestbook-service/)
11 | - [Kubernetes files](kubernetes/)
12 |
13 | The latest HTML version of this Lab is available [here](http://bit.ly/kubernetes-lab)
14 |
15 |
--------------------------------------------------------------------------------
/frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | FROM bucharestgold/centos7-s2i-nodejs:10.x
17 |
18 | ADD . /opt/app-root/src/
19 |
20 | WORKDIR /opt/app-root/src
21 |
22 | RUN ["/bin/bash", "-c", "npm install"]
23 |
24 | EXPOSE 8080
25 |
26 | CMD /bin/bash -c 'npm start'
--------------------------------------------------------------------------------
/guestbook-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | FROM fabric8/java-jboss-openjdk8-jdk:1.1.7
17 |
18 | ENV JAVA_APP_JAR guestbook-service-swarm.jar
19 | ENV AB_OFF true
20 | ENV JAVA_OPTIONS -Xmx512m
21 |
22 | EXPOSE 8080
23 |
24 | ADD target/guestbook-service-swarm.jar /app/
--------------------------------------------------------------------------------
/kubernetes/mysql-pv.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | apiVersion: v1
16 | kind: PersistentVolume
17 | metadata:
18 | name: pv001
19 | spec:
20 | capacity:
21 | storage: 1Gi
22 | accessModes:
23 | - ReadWriteOnce
24 | persistentVolumeReclaimPolicy: Recycle
25 | hostPath:
26 | path: /data/pv001
--------------------------------------------------------------------------------
/guestbook-service/src/main/resources/import.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- JBoss, Home of Professional Open Source
3 | -- Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
4 | -- contributors by the @authors tag. See the copyright.txt in the
5 | -- distribution for a full listing of individual contributors.
6 | --
7 | -- Licensed under the Apache License, Version 2.0 (the "License");
8 | -- you may not use this file except in compliance with the License.
9 | -- You may obtain a copy of the License at
10 | -- http://www.apache.org/licenses/LICENSE-2.0
11 | -- Unless required by applicable law or agreed to in writing, software
12 | -- distributed under the License is distributed on an "AS IS" BASIS,
13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | -- See the License for the specific language governing permissions and
15 | -- limitations under the License.
16 | --
17 |
18 | -- You can use this file to load seed data into the database using SQL statements
19 | insert into Message (id, username, message, timestamp) values (99999, 'Benevides', 'Hello World', '2015-06-10 22:10:00');
--------------------------------------------------------------------------------
/kubernetes/mysql-pvc.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | kind: PersistentVolumeClaim
17 | apiVersion: v1
18 | metadata:
19 | name: mysql-pvc
20 | labels:
21 | app: mysql
22 | lab: kubernetes-lab
23 | spec:
24 | accessModes:
25 | - ReadWriteOnce
26 | resources:
27 | requests:
28 | storage: 1Gi
--------------------------------------------------------------------------------
/kubernetes/guestbookservice-service.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | kind: Service
17 | apiVersion: v1
18 | metadata:
19 | name: guestbook-service
20 | labels:
21 | app: guestbook-service
22 | lab: kubernetes-lab
23 | spec:
24 | ports:
25 | - port: 8080
26 | targetPort: 8080
27 | selector:
28 | app: guestbook-service
--------------------------------------------------------------------------------
/kubernetes/helloworldservice-service.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | kind: Service
17 | apiVersion: v1
18 | metadata:
19 | name: helloworld-service-vertx
20 | labels:
21 | app: helloworld-service-vertx
22 | lab: kubernetes-lab
23 | spec:
24 | ports:
25 | - port: 8080
26 | targetPort: 8080
27 | selector:
28 | app: helloworld-service-vertx
--------------------------------------------------------------------------------
/kubernetes/frontend-service.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | kind: Service
17 | apiVersion: v1
18 | metadata:
19 | name: frontend-ui
20 | labels:
21 | app: frontend-ui
22 | lab: kubernetes-lab
23 | spec:
24 | type: LoadBalancer
25 | ports:
26 | - port: 80
27 | name: http-80
28 | targetPort: http
29 | selector:
30 | app: frontend-ui
--------------------------------------------------------------------------------
/kubernetes/mysql-service.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | apiVersion: v1
17 | kind: Service
18 | metadata:
19 | name: mysql
20 | labels:
21 | app: mysql
22 | lab: kubernetes-lab
23 | spec:
24 | ports:
25 | # the port that this service should serve on
26 | - port: 3306
27 | # label keys and values that must match in order to receive traffic for this service
28 | selector:
29 | app: mysql
--------------------------------------------------------------------------------
/helloworld-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | FROM fabric8/java-jboss-openjdk8-jdk:1.1.7
17 |
18 | ENV JAVA_APP_JAR helloworld-service-fat.jar
19 | ENV AB_OFF true
20 |
21 | ADD target/helloworld-service-fat.jar /app/
22 | ADD config.json /app/
23 |
24 | EXPOSE 8080
25 | CMD []
26 |
27 | ENTRYPOINT ["java", "-Dvertx.disableFileCPResolving=true", "-Xmx256m", "-jar", "/app/helloworld-service-fat.jar"]
28 |
29 |
--------------------------------------------------------------------------------
/lab/feedback.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ## Codelab feedback
17 |
18 | ****
19 | - The codelab was easy and useful
20 | - The codelab was too complicated
21 | - The codelab didn’t go far enough
22 | - I had some technical difficulties
23 | ****
24 |
25 | If you find any issues, report it in the link:https://github.com/redhat-developer-demos/kubernetes-lab/issues[Github repository]. You're also welcome to send any link:https://help.github.com/articles/using-pull-requests/[pull requests] and contributions.
--------------------------------------------------------------------------------
/lab/docker-image-minishift.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | Minishift allows the developer to have access to the internal docker daemon and registry. With the access to the internal docker daemon, you can build a new version of the image and make it available in the internal registry.
17 |
18 | To access the internal docker daemon run the following command:
19 |
20 | [source,bash, subs="normal,attributes"]
21 | ----
22 | $ eval $(minishift docker-env)
23 | ----
24 |
25 | Now you can buid the docker image and it will be automatically avaible in the docker registry of minishift.
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/data/MessageRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.guestbook.data;
18 |
19 | import java.util.List;
20 |
21 | import org.apache.deltaspike.data.api.EntityRepository;
22 | import org.apache.deltaspike.data.api.Query;
23 | import org.apache.deltaspike.data.api.Repository;
24 |
25 | @Repository
26 | public interface MessageRepository extends EntityRepository {
27 |
28 | @Query("SELECT m FROM Message m ORDER BY m.timestamp DESC")
29 | List findAllOrdered();
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/kubernetes/frontend-deployment.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | apiVersion: extensions/v1beta1
17 | kind: Deployment
18 | metadata:
19 | name: frontend-ui
20 | labels:
21 | app: frontend-ui
22 | lab: kubernetes-lab
23 | spec:
24 | replicas: 2
25 | selector:
26 | matchLabels:
27 | app: frontend-ui
28 | template:
29 | metadata:
30 | labels:
31 | app: frontend-ui
32 | lab: kubernetes-lab
33 | spec:
34 | containers:
35 | - name: frontend-ui
36 | image: rafabene/microservices-frontend:1.0
37 | ports:
38 | - name: http
39 | containerPort: 8080
--------------------------------------------------------------------------------
/lab/configuring-application.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Configuring Your Application
17 | Duration: 20:00
18 |
19 | The Helloworld Service is configured to return a message that uses the following template:
20 | [source,subs="normal,attributes"]
21 | ----
22 | Hello {name} from {hostname} with {version}
23 | ----
24 |
25 | There are several ways to update this configuration. We'll go through a couple of them, including:
26 |
27 | * Environment variable
28 | * Command line argument
29 | * And, ConfigMap
30 |
31 | include::configuring-envvars.adoc[]
32 |
33 | // include::configuring-argument.adoc[]
34 |
35 | include::configuring-configmap.adoc[]
36 |
37 |
--------------------------------------------------------------------------------
/kubernetes/guestbookservice-deployment.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | apiVersion: extensions/v1beta1
17 | kind: Deployment
18 | metadata:
19 | name: guestbook-service
20 | labels:
21 | app: guestbook-service
22 | lab: kubernetes-lab
23 | spec:
24 | replicas: 1
25 | selector:
26 | matchLabels:
27 | app: guestbook-service
28 | template:
29 | metadata:
30 | labels:
31 | app: guestbook-service
32 | lab: kubernetes-lab
33 | spec:
34 | containers:
35 | - name: guestbook-service
36 | image: rafabene/microservices-guestbook:1.0
37 | ports:
38 | - name: http
39 | containerPort: 8080
40 |
--------------------------------------------------------------------------------
/kubernetes/helloworldservice-deployment.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | apiVersion: extensions/v1beta1
17 | kind: Deployment
18 | metadata:
19 | name: helloworld-service-vertx
20 | labels:
21 | app: helloworld-service-vertx
22 | lab: kubernetes-lab
23 | spec:
24 | replicas: 2
25 | selector:
26 | matchLabels:
27 | app: helloworld-service-vertx
28 | template:
29 | metadata:
30 | labels:
31 | app: helloworld-service-vertx
32 | lab: kubernetes-lab
33 | spec:
34 | containers:
35 | - name: helloworld-service-vertx
36 | image: rafabene/microservices-helloworld-vertx:1.0
37 | ports:
38 | - name: http
39 | containerPort: 8080
40 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/rest/JaxRsActivator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.guestbook.rest;
18 |
19 | import javax.ws.rs.ApplicationPath;
20 | import javax.ws.rs.core.Application;
21 |
22 | /**
23 | * A class extending {@link Application} and annotated with @ApplicationPath is
24 | * the Java EE 7 "no XML" approach to activating JAX-RS.
25 | *
26 | *
27 | * Resources are served relative to the servlet path specified in the
28 | * {@link ApplicationPath} annotation.
29 | *
30 | */
31 | @ApplicationPath("/api")
32 | public class JaxRsActivator extends Application {
33 | /* class body intentionally left blank */
34 | }
--------------------------------------------------------------------------------
/guestbook-service/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
21 |
26 |
27 | org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/resources/META-INF/persistence.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
17 |
18 | java:jboss/datasources/MySQLDS
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/lab/app-application-source.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Get the Guestbook source
17 | Duration: 3:00
18 |
19 | Start by cloning the github repository for the Guestbook application and move into the kubernetes examples directory.
20 |
21 | [source, bash, subs="normal,attributes"]
22 | ----
23 | $ *git clone https://github.com/redhat-developer-demos/kubernetes-lab*
24 | $ *cd kubernetes-lab/kubernetes*
25 | ----
26 |
27 | Kubernetes resources can be specified using link:http://yaml.org/[yaml] or link:http://www.json.org/[json] formats.
28 | We will be using the yaml files in this directory to decribe and deploy the Kubernetes objects in our development environment. You are definitely encouraged to read them and see how pods, services, and others are declared. We’ll walk through a couple of these files in detail.
29 |
30 |
--------------------------------------------------------------------------------
/lab/references.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ## References
17 |
18 | - link:http://bit.ly/k8s-lab[Google's Kubernetes lab] by link:https://twitter.com/saturnism[Ray Tsang]
19 | - link:https://github.com/redhat-developer-demos/docker-java[docker for Java Developers] by link:https://twitter.com/rhdevelopers[Red Hat Developers]
20 | - link:https://docs.openshift.com/enterprise/3.2/welcome/index.html[OpenShift] docs
21 | - link:http://kubernetes.io/docs/[Kubernetes] docs
22 | - link:http://vertx.io/[Vert.X] - a tool-kit for building reactive applications on the JVM
23 | - link:http://wildfly-swarm.io/[WildFly Swarm] - A link:http://microprofile.io/[Microprofile] application server
24 | - Red Hat's link:http://developers.redhat.com/products/cdk/[CDK] - Container Development Kit
25 | - link:https://github.com/redhat-helloworld-msa/helloworld-msa[Helloworld-MSA] - Your microservices sandbox in CDK.
--------------------------------------------------------------------------------
/lab/app-frontend-service.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Deploy a frontend Service
17 | Duration 3:00
18 |
19 | Each Pod has a unique IP address - but the address is ephemeral. The Pod IP addresses are not stable and it can change when Pods start and/or restart. A service provides a single access point to a set of pods matching some constraints. A Service IP address is stable.
20 |
21 | Create the frontend service:
22 |
23 | [source, bash, subs="normal,attributes"]
24 | ----
25 | $ *kubectl create -f frontend-service.yaml*
26 | service/frontend-ui created
27 | ----
28 |
29 | And check it:
30 |
31 | [source, bash, subs="normal,attributes"]
32 | ----
33 | $ *kubectl get services*
34 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
35 | frontend-ui LoadBalancer 172.30.58.95 172.29.26.18,172.29.26.18 80:31391/TCP 8s
36 | ----
37 |
38 |
--------------------------------------------------------------------------------
/lab/graceful-shutdown.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Graceful Shutdown
17 | Duration: 5:00
18 |
19 | When a pod needs to be deleted (such as reducing the number of replicas), Kubernetes will send the SIGTERM signal to the process. The process should perform all the cleanups. However, we cannot wait forever for the process to exit. By default, Kubernetes waits 30 seconds before sending the final SIGKILL signal to kill the process. If your process needs more or less time, you can configure this through termination grace periods configuration (see link:http://kubernetes.io/docs/user-guide/pods/#termination-of-pods[guide]).
20 |
21 | Optionally, you can also ask Kubernetes to execute a shutdown command via the pre-stop lifecycle hook. Read through the link:http://kubernetes.io/docs/user-guide/pods/#termination-of-pods[documentation] the learn more - we won't implement this during the lab.
22 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/Resources.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.guestbook;
18 |
19 | import javax.enterprise.context.RequestScoped;
20 | import javax.enterprise.inject.Disposes;
21 | import javax.enterprise.inject.Produces;
22 | import javax.persistence.EntityManager;
23 | import javax.persistence.EntityManagerFactory;
24 | import javax.persistence.PersistenceUnit;
25 |
26 | /**
27 | * This class uses CDI to alias Java EE resources, such as the persistence
28 | * context, to CDI beans
29 | *
30 | *
31 | * Example injection on a managed bean field:
32 | *
38 | */
39 | public class Resources {
40 |
41 | @PersistenceUnit
42 | private EntityManagerFactory emf;
43 |
44 | @Produces
45 | @RequestScoped
46 | public EntityManager create() {
47 | return emf.createEntityManager();
48 | }
49 |
50 | public void close(@Disposes EntityManager em) {
51 | if (em.isOpen()) {
52 | em.close();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/lab/configuring-envvars.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #### Environmental Variable
17 |
18 | http://vertx.io/[Vert.X] can read the override configuration directly from an environment variable. In this case, the environment variable is defaulted to _greeting_. You can specify the environmental variable directly using the _oc_ command:
19 |
20 | [source, bash, subs="normal,attributes"]
21 | ----
22 | $ *oc set env deployment helloworld-service-vertx GREETING='Hello {name} from envvar!'*
23 | deployment "helloworld-service-vertx" updated
24 | ----
25 |
26 | Again, through the use of *Kubernetes Deployment*, it'll rolling update all the replicas with the new configuration! If you were to refresh the application, you'll notice that there are no intermittent errors because we also have health checks and readiness checks in place.
27 |
28 | Check the application to see it is using the new Greeting string.
29 |
30 | Let's remove the defined variable:
31 |
32 | [source, bash, subs="normal,attributes"]
33 | ----
34 | $ *oc set env deployment helloworld-service-vertx GREETING-*
35 | deployment "helloworld-service-vertx" updated
36 | ----
37 |
38 | NOTE: The '-' means that we want to remove that environment var from the Deployment.
--------------------------------------------------------------------------------
/kubernetes/mysql-deployment.yaml:
--------------------------------------------------------------------------------
1 | # JBoss, Home of Professional Open Source
2 | # Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | # contributors by the @authors tag. See the copyright.txt in the
4 | # distribution for a full listing of individual contributors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | apiVersion: extensions/v1beta1
17 | kind: Deployment
18 | metadata:
19 | name: mysql
20 | labels:
21 | app: mysql
22 | lab: kubernetes-lab
23 | spec:
24 | replicas: 1
25 | selector:
26 | matchLabels:
27 | app: mysql
28 | template:
29 | metadata:
30 | labels:
31 | app: mysql
32 | lab: kubernetes-lab
33 | spec:
34 | containers:
35 | - name: mysql
36 | image: openshift/mysql-56-centos7
37 | imagePullPolicy: IfNotPresent
38 | resources:
39 | limits :
40 | cpu: 0.5
41 | env:
42 | - name: MYSQL_USER
43 | value: myuser
44 | - name: MYSQL_PASSWORD
45 | value: mypassword
46 | - name: MYSQL_DATABASE
47 | value: guestbook
48 | ports:
49 | - containerPort: 3306
50 | name: mysql
51 | volumeMounts:
52 | # name must match the volume name below
53 | - name: mysql-persistent-volume
54 | # mount path within the container
55 | mountPath: /var/lib/mysql/data
56 | volumes:
57 | - name: mysql-persistent-volume
58 | persistentVolumeClaim:
59 | claimName: mysql-pvc
60 |
--------------------------------------------------------------------------------
/frontend/scripts/page.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 | fillMessages();
3 | });
4 |
5 | // Action on submit
6 | function submitForm(event) {
7 | var myForm = $('#myform');
8 | if (myForm[0].checkValidity()) {
9 | // Prevent submission
10 | event.preventDefault();
11 | // POST the form
12 | $.post('/api/messages', myForm.serialize(), function() {
13 | // Clear the message
14 | $('#inputMessage').val('');
15 | // Get the hello
16 | getHelloworld();
17 | // Fill the table
18 | fillMessages();
19 | }).fail(function(data) {
20 | alert('Failed to post form. Please check the logs for more details.')
21 | console.log(data);
22 | });
23 | } else {
24 | // simulate a submit to force HTML5 validation
25 | $('').hide().appendTo(myForm).click().remove();
26 | }
27 | }
28 |
29 | // get the hello world message
30 | function getHelloworld() {
31 | $.ajax({
32 | url : '/api/hello/' + $('#inputUsername').val(),
33 | success : function(result) {
34 | $('#message').text(result);
35 | $('#messageBox').removeClass('hidden');
36 | },
37 | error : function(request, status, error) {
38 | alert('Error getting the helloworld message. Please check the logs for more details.');
39 | },
40 | });
41 | }
42 |
43 | // get the existing messages
44 | function fillMessages() {
45 | // wait at least 200ms before requesting the page
46 | setTimeout(function() {
47 | $.ajax({
48 | url : '/api/messages',
49 | success : function(result) {
50 | var messages = JSON.parse(result);
51 | // Clear the table before feeling it again
52 | $('#mytable tbody').empty();
53 | for ( var i in messages) {
54 | $('#mytable tbody').append(
55 | '
' + messages[i].username + '
' + messages[i].message + '
');
56 | }
57 | },
58 | error : function(request, status, error) {
59 | alert('Error reading the messages. Please check the logs for more details.');
60 | },
61 | });
62 |
63 | }, 200);
64 | }
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/rest/MessageResource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.guestbook.rest;
18 |
19 | import java.util.List;
20 |
21 | import javax.inject.Inject;
22 | import javax.ws.rs.FormParam;
23 | import javax.ws.rs.GET;
24 | import javax.ws.rs.POST;
25 | import javax.ws.rs.Path;
26 | import javax.ws.rs.Produces;
27 | import javax.ws.rs.core.Response;
28 |
29 | import com.redhat.developers.guestbook.data.Message;
30 | import com.redhat.developers.guestbook.data.MessageRepository;
31 |
32 | @Path("/messages")
33 | public class MessageResource {
34 |
35 | @Inject
36 | private MessageRepository messageRepository;
37 |
38 | @Inject
39 | private BadwordFilter badwordFilter;
40 |
41 | @POST
42 | public Response addMessage(@FormParam("username") String username, @FormParam("message") String text) {
43 | String input = badwordFilter.filterText(text);
44 | Message message = new Message(username, input);
45 | try {
46 | messageRepository.save(message);
47 | } catch (Exception e) {
48 | return Response.serverError().entity(e.getMessage()).build();
49 | }
50 | return Response.ok().build();
51 | }
52 |
53 | @GET
54 | @Produces("application/json")
55 | public List getAllMessages() {
56 | return messageRepository.findAllOrdered();
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/Main.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.guestbook;
18 |
19 | import org.wildfly.swarm.container.Container;
20 | import org.wildfly.swarm.datasources.DatasourcesFraction;
21 |
22 | public class Main {
23 |
24 | public static void main(String[] args) throws Exception {
25 | Container container = new Container();
26 |
27 | container.fraction(new DatasourcesFraction().jdbcDriver("com.mysql", (d) -> {
28 | d.driverClassName("com.mysql.jdbc.Driver");
29 | d.xaDatasourceClass("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
30 | d.driverModuleName("com.mysql");
31 | }).dataSource("MySQLDS", (ds) -> {
32 | ds.driverName("com.mysql");
33 | ds.connectionUrl(System.getenv().getOrDefault("JDBC_URL", "jdbc:mysql://mysql:3306/guestbook?useSSL=false&autoReconnect=true"));
34 | ds.userName(System.getenv().getOrDefault("DATASOURCE_USERNAME", "myuser"));
35 | ds.password(System.getenv().getOrDefault("DATASOURCE_PASSWORD", "mypassword"));
36 | ds.backgroundValidation(true);
37 | ds.validConnectionCheckerClassName("org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker");
38 | ds.validateOnMatch(true);
39 | ds.checkValidConnectionSql("SELECT 1");
40 | }));
41 |
42 | // Start the container and deploy the default war
43 | container.start().deploy();
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/data/Message.java:
--------------------------------------------------------------------------------
1 | /*
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.guestbook.data;
18 |
19 | import java.io.Serializable;
20 | import java.util.Date;
21 |
22 | import javax.persistence.Entity;
23 | import javax.persistence.GeneratedValue;
24 | import javax.persistence.Id;
25 | import javax.validation.constraints.NotNull;
26 | import javax.validation.constraints.Size;
27 |
28 | @Entity
29 | public class Message implements Serializable {
30 |
31 | private static final long serialVersionUID = 1L;
32 |
33 | @Id
34 | @GeneratedValue
35 | private Long id;
36 |
37 | @NotNull
38 | @Size(min = 3, max = 20)
39 | private String username;
40 |
41 | @NotNull
42 | @Size(min = 5)
43 | private String message;
44 |
45 | private Date timestamp = new Date();
46 |
47 | public Message() {
48 |
49 | }
50 |
51 | public Message(String username, String message) {
52 | this.username = username;
53 | this.message = message;
54 | }
55 |
56 | public String getUsername() {
57 | return username;
58 | }
59 |
60 | public void setUsername(String username) {
61 | this.username = username;
62 | }
63 |
64 | public String getMessage() {
65 | return message;
66 | }
67 |
68 | public void setMessage(String message) {
69 | this.message = message;
70 | }
71 |
72 | public Long getId() {
73 | return id;
74 | }
75 |
76 | public Date getTimestamp() {
77 | return timestamp;
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/lab/troubleshooting.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ## Troubleshooting
17 |
18 | ### Error from server: the server has asked for the client to provide credentials
19 |
20 | If any **kubectl** or **oc** command replies with
21 |
22 | ====
23 | Error from server: the server has asked for the client to provide credentials
24 | ====
25 |
26 | Execute:
27 |
28 | [source,bash,subs="normal,attributes"]
29 | ----
30 | $ *oc login -u openshift-dev -p devel*
31 | ----
32 |
33 |
34 | ### Windows vagrant plugin install
35 |
36 | When your Windows username contains a space, vagrant will give the following message:
37 |
38 | ====
39 | The directory where plugins are installed (the Vagrant home directory) has a space in it. On Windows, there is a bug in Ruby when compiling plugins into directories with spaces. Please move your Vagrant home directory to a path without spaces and try again.
40 | ====
41 |
42 | The workaround is set the vagrant home in other folder that doesn't contain spaces. You can do that with the following command:
43 |
44 | [source,bash,subs="normal,attributes"]
45 | ----
46 | C:\> set VAGRANT_HOME=C:\
47 | ----
48 |
49 |
50 | ### Windows vagrant ssh
51 |
52 | If your Windows doesn't contain *ssh*, vagrant will complain about it. In that case, just install *git for Windows* and add the following values to the PATH environment variable to **C:\Program Files\Git\bin;C:\Program Files\Git\usr\bin**
53 |
54 | image::images/vagrant-windows-git.png[Logo,float="center",align="center"]
--------------------------------------------------------------------------------
/lab/app-deploy-mysql-and-service.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Deploy MySQL and Service
17 | Duration: 4:00
18 |
19 | MySQL uses persistent storage. Rather than writing the data directly into the container image itself, our example stores the MySQL in a Persistent Volume. Before you can deploy the pod, you need to claim a persistent volume that can be mounted inside of the MySQL container:
20 |
21 | [source, bash, subs="normal,attributes"]
22 | ----
23 | $ *kubectl create -f mysql-pvc.yaml*
24 | persistentvolumeclaim/mysql-pvc created
25 | ----
26 |
27 | CDK provides several *PersistentVolumes*, previously defined by the cluster administrator. These *PersistentVolumes* will be assigned based on the size claimed by the *PersistentVolumeClaim*.
28 |
29 | You can examine the *PersistentVolumeClaim* with the following command:
30 |
31 | [source, bash, subs="normal,attributes"]
32 | ----
33 | $ *kubectl get pvc*
34 | NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
35 | mysql-pvc Bound pv0044 100Gi RWO,ROX,RWX 27s
36 | ----
37 |
38 | You can then deploy both the MySQL Pod and the Service with a single command:
39 |
40 | [source, bash, subs="normal,attributes"]
41 | ----
42 | $ *kubectl create -f mysql-deployment.yaml -f mysql-service.yaml*
43 | deployment.extensions/mysql created
44 | service/mysql created
45 | ----
46 |
47 | Lastly, you can see the pods and service status via the command line. Recall the command you can use to see the status (hint: _kubectl get ..._). Make sure the status is _Running_ before continuing.
48 |
--------------------------------------------------------------------------------
/lab/configuring-argument.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #### Command Line Argument
17 |
18 | Next, let's add a configuration via the command line arguments. You can also use _oc_ to edit the *DeploymentConfig*.
19 |
20 | [source, bash, subs="normal,attributes"]
21 | ----
22 | $ *oc edit deployment helloworld-service-vertx*
23 | ----
24 | include::includes/tip.adoc[]
25 |
26 |
27 | Now you can add the *args* that will be passed to the container command.
28 |
29 | [source, yaml, subs="normal,attributes"]
30 | ----
31 | apiVersion: extensions/v1beta1
32 | kind: Deployment
33 | ...
34 | spec:.
35 | ...
36 | template:
37 | ...
38 | spec:
39 | ...
40 | containers:
41 | - image: rafabene/microservices-helloworld-vertx:1.0
42 | *args:
43 | - -DGREETING=Hello {name} from args*
44 | ...
45 | ----
46 |
47 | [NOTE]
48 | ====
49 | Yes, there are 2 dashes. The first dash is required by YAML to indicate that this is a list element, followed by a space and one more dash that is actually passed into the command line argument.
50 |
51 | When you save the file in *vi*, the new content is automatically submited to the cluster. This causes the *Kubernetes Deployment* to automatically perform a rolling update of all Pods to have the changes that you just specified.
52 | ====
53 |
54 | Check the application and submit a name and message to see it is using the new greeting string.
55 |
56 | Let's rollback to the previous state again:
57 |
58 | [source, bash, subs="normal,attributes"]
59 | ----
60 | $ *oc rollback helloworld-service-vertx*
61 | #? rolled back to helloworld-service-vertx-?
62 | ----
--------------------------------------------------------------------------------
/helloworld-service/src/main/java/com/redhat/developers/helloworld/HelloworldVerticle.java:
--------------------------------------------------------------------------------
1 | /**
2 | * JBoss, Home of Professional Open Source
3 | * Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
4 | * contributors by the @authors tag. See the copyright.txt in the
5 | * distribution for a full listing of individual contributors.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.developers.helloworld;
18 |
19 | import java.util.HashMap;
20 | import java.util.Map;
21 |
22 | import org.apache.commons.lang3.text.StrSubstitutor;
23 |
24 | import io.vertx.core.AbstractVerticle;
25 | import io.vertx.core.http.HttpMethod;
26 | import io.vertx.ext.web.Router;
27 | import io.vertx.ext.web.handler.CorsHandler;
28 |
29 | public class HelloworldVerticle extends AbstractVerticle {
30 |
31 | public static final String version = "1.0";
32 |
33 | @Override
34 | public void start() throws Exception {
35 | Router router = Router.router(vertx);
36 |
37 | //Config CORS
38 | router.route().handler(CorsHandler.create("*")
39 | .allowedMethod(HttpMethod.GET)
40 | .allowedHeader("Content-Type"));
41 |
42 | // hello endpoint
43 | router.get("/api/hello/:name").handler(ctx -> {
44 | ctx.response().end(hello(ctx.request().getParam("name")));
45 | });
46 | vertx.createHttpServer().requestHandler(router::accept).listen(8080);
47 | }
48 |
49 | private String hello(String name) {
50 | String configGreeting = ApplicationConfiguration.load(config()).getString("GREETING");
51 | String greeting = configGreeting == null ? "Hello {name} from {hostname} with {version}" : configGreeting;
52 | Map values = new HashMap();
53 | values.put("name", name);
54 | values.put("hostname", System.getenv().getOrDefault("HOSTNAME", "unknown"));
55 | values.put("version", version);
56 | return new StrSubstitutor(values, "{", "}").replace(greeting);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/lab/rolling-update.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Rolling Update
17 | Duration: 10:00
18 |
19 | It’s easy to update & rollback.
20 |
21 | In this lab, we'll switch to the _frontend/_ directory and make a minor change to the index.html (e.g., change the background color, title, etc.). After that, rebuild the container.
22 |
23 |
24 | [source, bash, subs="normal,attributes"]
25 | ----
26 | $ *cd kubernetes-lab/frontend*
27 | $ *vi index.html*
28 | ----
29 | [TIP]
30 | ====
31 | HINT 1: Change the _
Say Hi
_ line, but feel free to change any HTML content that that you want
32 |
33 | HINT 2: Type *':51'* to go to that line
34 |
35 | HINT 3: Type *'i'* to enter in edit mode
36 |
37 | HINT 4: Type *':wq'* to exit from vi
38 | ====
39 |
40 | Kubernetes needs to be aware of the new docker image with the changes that you introduced.
41 |
42 | // include::docker-image-minishift.adoc[]
43 |
44 | TIP: Replace rafabene/microservices-frontend:2.0 to /microservices-frontend:2.0
45 |
46 | [source, bash, subs="normal,attributes"]
47 | ----
48 | $ *docker build -t /microservices-frontend:2.0 .*
49 |
50 | $ *docker push /microservices-frontend:2.0*
51 | ----
52 |
53 | Now we will use the _kubectl rolling-update_ command to perform the rolling update. We create a new *ReplicationController* called frontend-ui-2 that contains the new image.
54 |
55 | [source,bash, subs="normal,attributes"]
56 | ----
57 | $ *kubectl set image deployment/frontend-ui frontend-ui=rafabene/microservices-frontend:2.0*
58 | deployment.extensions/frontend-ui image updated
59 | ----
60 |
61 | That's it! Kubernetes will performed a rolling update to update all the versions from 1.0 to 2.0.
62 |
63 |
--------------------------------------------------------------------------------
/lab/setup-environment.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ## Setup environment
17 | Duration: 15:00
18 |
19 | This section describes what, how, and where to install the software needed for this lab. This lab is designed for a BYOL (Bring Your Own Laptop) style hands-on-lab.
20 |
21 | ### Hardware
22 |
23 | - Operating System: Windows 7 (SP1), Mac OS X (10.8 or later), Fedora (21 or later)
24 | - Memory: At least 4 GB+, preferred 8 GB
25 |
26 | ### Software
27 |
28 | #### Development tools
29 |
30 | Make sure to have the following tools/packages installed:
31 |
32 | - GIT
33 | - Maven
34 | - Kubernetes binaries ( )
35 |
36 | #### kubectl
37 |
38 | To install kubectl binary, follow the link:https://kubernetes.io/docs/tasks/tools/install-kubectl/[Install and Set Up kubectl] tutorial
39 |
40 | TIP: macOS users can install `kubectl` through homebrew using the following command `brew install kubectl`
41 |
42 | #### oc
43 |
44 | To install oc, Download it from https://github.com/openshift/origin/releases
45 |
46 | TIP: macOS users can isntall `oc` through homebrew using the following command: `brew install openshift-cli`
47 |
48 | ### Login in the cluster
49 |
50 | This lab uses link:https://www.openshift.org/[OpenShift], which is an Enterprise distribution of Kubernetes. Because of some Enterprise features like security, it's needed to authenticate against this cluster.
51 |
52 | To authenticate in the cluster, you need to access to the `oc` binary. You can add the oc binary to you path by running the following command:
53 |
54 | [source,bash,subs="normal,attributes"]
55 | ----
56 | # Login in the cluster
57 | $ oc login {ocp-cluster}
58 | ----
59 |
60 | The credentials are: userX / openshift. X is your assigned number
61 |
62 | Next, you will need to create a project for you:
63 |
64 | [source,bash,subs="normal,attributes"]
65 | ----
66 | # Create a new project. X is your number
67 | $ oc new-project labX
68 | ----
69 |
--------------------------------------------------------------------------------
/lab/autoscaling.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Autoscaling
17 | Duration: 5:00
18 |
19 | Kubernetes 1.2 has built-in Horizontal Pod Autoscaling based on CPU utilization (and custom metrics!). We will only cover autoscaling based on CPU utilization in this lab, since the custom metrics scaling is still in Alpha.
20 |
21 | To set up horizontal autoscaling is extremely simple:
22 |
23 | [source, bash, subs="normal,attributes"]
24 | ----
25 | $ *oc autoscale deployment guestbook-service --min 1 --max 10 --cpu-percent=80*
26 | deployment "guestbook-service" autoscaled
27 | ----
28 |
29 | [NOTE]
30 | ====
31 | - Currently, the only metric supported is CPU Utilization.
32 | - The OpenShift administrator must first enable link:https://docs.openshift.com/enterprise/3.2/install_config/cluster_metrics.html[Cluster Metrics] before you can enable autoscaling.
33 | - The OpenShift administrator must also enable link:https://docs.openshift.com/enterprise/3.2/admin_guide/limits.html[Resource Limits] on the project.
34 | ====
35 |
36 | Behind the scenes, Kubernetes will periodically (by default, every 30 seconds) collect CPU utilization and determine the number of pods needed.
37 |
38 | You can see the current status of the autoscaler by using the describe command:
39 |
40 | [source, bash, subs="normal,attributes"]
41 | ----
42 | $ *oc describe hpa guestbook-service*
43 | Name: guestbook-service
44 | Namespace: myproject
45 | Labels:
46 | Annotations:
47 | CreationTimestamp: Thu, 04 Aug 2016 06:59:05 -0400
48 | Reference: Deployment/guestbook-service
49 | Target CPU utilization: 80%
50 | Current CPU utilization:
51 | Min replicas: 1
52 | Max replicas: 10
53 | ReplicationController pods: 1 current / 1 desired
54 | Events:
55 | ....
56 | ----
57 |
58 | It's going to be a little difficult to enable the Cluster Metrics and generate the load needed to kick off the autoscaler. We won't do that during the lab.
59 |
60 | Learn more about Horizontal Pod Autoscaling (HPA) in the https://docs.openshift.com/enterprise/3.2/dev_guide/pod_autoscaling.html[guide]
61 |
--------------------------------------------------------------------------------
/lab/readme.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | # Kubernetes Lab for Java Developers
17 | from Basics to OpenShift
18 | :toc: macro
19 | :toc-title: Table of Contents
20 | :toclevels: 5
21 | :icons: font
22 | :data-uri:
23 | :source-highlighter: highlightjs
24 | :numbered:
25 | :ocp-cluster: master.devx-5c72.openshiftworkshop.com
26 | :app-domain: apps.devx-5c72.openshiftworkshop.com
27 |
28 | Latest HTML: http://bit.ly/kubernetes-lab +
29 | Docs and Application Source code: https://github.com/redhat-developer-demos/kubernetes-lab
30 |
31 | If you find any issues, report it in the link:https://github.com/redhat-developer-demos/kubernetes-lab/issues[Github repository]. You're also welcome to send any link:https://help.github.com/articles/using-pull-requests/[pull requests] and contributions.
32 |
33 | toc::[]
34 |
35 | include::preface.adoc[]
36 |
37 | include::setup-environment.adoc[]
38 |
39 | ## Kubernetes - The Basics
40 |
41 | We’re going to work through this https://github.com/redhat-developer-demos/kubernetes-lab[Guestbook] example. This example has a frontend using HTML5 and Javascript (client-side and server-side), and two microservices built using link:http://wildfly-swarm.io[WildFly Swarm] and link:http://vertx.io/[VertX]. It requires MySQL to store guestbook entries.
42 |
43 | image::images/app-diagram.png[Logo,float="center",align="center"]
44 |
45 | include::app-application-source.adoc[]
46 |
47 | include::app-frontend-deployment.adoc[]
48 |
49 | include::app-frontend-service.adoc[]
50 |
51 | include::app-deploy-mysql-and-service.adoc[]
52 |
53 | include::app-deploy-microservices.adoc[]
54 |
55 | include::external-access.adoc[]
56 |
57 | include::scaling.adoc[]
58 |
59 | include::health-checks.adoc[]
60 |
61 | include::rolling-update.adoc[]
62 |
63 | include::graceful-shutdown.adoc[]
64 |
65 | ## Kubernetes - Going further
66 |
67 | include::openshift.adoc[]
68 |
69 | include::configuring-application.adoc[]
70 |
71 | include::managing-credentials.adoc[]
72 |
73 | include::autoscaling.adoc[]
74 |
75 | include::extra.adoc[]
76 |
77 | include::feedback.adoc[]
78 |
79 | include::troubleshooting.adoc[]
80 |
81 | include::references.adoc[]
82 |
83 |
--------------------------------------------------------------------------------
/frontend/frontend.js:
--------------------------------------------------------------------------------
1 | /**
2 | * JBoss, Home of Professional Open Source Copyright 2016, Red Hat, Inc. and/or
3 | * its affiliates, and individual contributors by the
4 | *
5 | * @authors tag. See the copyright.txt in the distribution for a full listing of
6 | * individual contributors.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 | * use this file except in compliance with the License. You may obtain a copy of
10 | * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
11 | * applicable law or agreed to in writing, software distributed under the
12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
13 | * OF ANY KIND, either express or implied. See the License for the specific
14 | * language governing permissions and limitations under the License.
15 | */
16 |
17 | var express = require('express')
18 | var request = require('request')
19 | var bodyParser = require('body-parser')
20 | var app = express()
21 |
22 | var guestbookendpoint = 'http://guestbook-service:8080/api/messages'
23 | var helloendpoint = 'http://helloworld-service-vertx:8080/api/hello/'
24 |
25 | // Creates a $request callback using $express objects
26 | var defaultHandling = function(res, next) {
27 | // Callback for $request
28 | return function(error, response, body) {
29 | if (!error && response.statusCode == 200) {
30 | res.send(body || '');
31 | } else {
32 | next(error)
33 | }
34 | }
35 | }
36 |
37 | // for parsing application/x-www-form-urlencoded
38 | app.use(bodyParser.urlencoded({
39 | extended : true
40 | }));
41 |
42 | // Static content routing
43 | app.use('/', express.static('.'))
44 |
45 | app.use('/api/health', function(req, res, next) {
46 | res.send('I am ok');
47 | });
48 |
49 | app.use('/api/version', function(req, res, next) {
50 | res.send('Version 1');
51 | });
52 |
53 | app.post('/api/messages', function(req, res, next) {
54 | console.log('POST content %s to %s', JSON.stringify(req.body), guestbookendpoint)
55 | // Make a POST to guestbook endpoint
56 | request.post({
57 | 'url' : guestbookendpoint,
58 | 'form' : req.body,
59 | 'timeout' : 1500
60 | }, defaultHandling(res, next))
61 | });
62 |
63 | app.get('/api/messages', function(req, res, next) {
64 | console.log('redirecting GET request to ' + guestbookendpoint)
65 | // Get messages from guestbook endpoint
66 | request({
67 | 'url' : guestbookendpoint,
68 | "timeout" : 1500
69 | }, defaultHandling(res, next))
70 | });
71 |
72 | app.get('/api/hello/:name', function(req, res, next) {
73 | var dest = helloendpoint + req.params.name
74 | console.log('redirecting GET request to ' + dest)
75 | // Get the hello world message from helloworld-vertx endpoint
76 | request({
77 | 'url' : dest,
78 | 'timeout' : 1500
79 | }, defaultHandling(res, next))
80 | });
81 |
82 | var server = app.listen(8080, '0.0.0.0', function() {
83 | var host = server.address().address
84 | var port = server.address().port
85 |
86 | console.log("Frontend service running at http://%s:%s", host, port)
87 | });
--------------------------------------------------------------------------------
/lab/preface.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ## Preface
17 |
18 | In the last 3 years, docker and linux containers have become the sensation of the IT industry. The promise of eliminating environment inconsistencies by packaging your software together with all its dependencies (files, libraries, environment variables, runtimes, etc) has driven Linux containers to emerge as a de-facto standard.
19 |
20 | Once your application is wrapped in a container, you don't need to lose time configuring a new environment. Running another "instance" of your application is easy and consumes less computational resources than typical Virtual Machines.
21 |
22 | Even though containers consume fewer computational resources, a single machine running a dozen containers is not an ideal scenario for a professional "production environment" --- running many containers on a single machine can lead to several issues.
23 |
24 | Just to mention a few:
25 |
26 | - The quantity of active containers are limited by the "size" of your hardware
27 | - Unlike a "cloud environment" you can't move the workloads to where you want
28 | - The one machine becomes the SPOF (Single Point of Failure) of your application.
29 |
30 | To achieve a serious "production environment", your Linux containers should be capable of running on more than one single machine, supporting your application's horizontal scaling. In this scenario, features like self-healing, autoscaling, load-balancing, service-discovery, and distributed storage volumes completes the professional touch of your environment. It sounds complicated, but fortunately you can get all of these features from a single technology - Kubernetes.
31 |
32 | link:http://kubernetes.io/[Kubernetes] is an open-source project developed by link:https://www.google.com/[Google], with link:https://developers.redhat.com/[Red Hat] at a close second in contributions. Google has over a decade of experience with Linux containers, deploying millions each day. It should be no surprise that Kubernetes' capabilities and maturity have led to its being used as the engine of link:https://www.openshift.com/[OpenShift Enterprise v3].
33 |
34 | image::images/k8slogo.png[Logo,float="center",align="center"]
35 |
36 | This lab offers developers a hands-on session with Kubernetes, from the basics concepts, to adding Java based microservices, to service scaling, to perform rolling deployments. This is a BYOL (bring your own laptop) session, so bring your Windows, OSX, or Linux laptop and be ready to dig into a tool that promises to be at the forefront of our industry for some time to come.
37 |
38 | NOTE: Latest content of this lab is always at https://github.com/redhat-developer-demos/kubernetes-lab[]
39 |
--------------------------------------------------------------------------------
/lab/scaling.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Scaling
17 | Duration: 5:00
18 |
19 | We have seem that *Deployments* keep the same ammount of replicas running. Let's check the number of pods again. Execute:
20 |
21 | [source, bash, subs="normal,attributes"]
22 | ----
23 | $ *kubectl get pods*
24 | NAME READY STATUS RESTARTS AGE
25 | frontend-ui-6jy22 1/1 Running 0 24m
26 | frontend-ui-7tcgx 1/1 Running 0 24m
27 | guestbook-service-gxjnx 1/1 Running 0 19m
28 | helloworld-service-vertx-edux9 1/1 Running 0 20m
29 | helloworld-service-vertx-lq1m0 1/1 Running 0 21m
30 | mysql-q9k7p 1/1 Running 0 21m
31 | ----
32 |
33 | Scaling the number of replicas of our Hello World service is as simple as running :
34 |
35 | [source, bash, subs="normal,attributes"]
36 | ----
37 | $ *kubectl scale deployment helloworld-service-vertx --replicas=6*
38 | deployment "helloworld-service-vertx" scaled
39 | ----
40 |
41 | You can very quickly see that the replication controller has been updated:
42 |
43 | [source, bash, subs="normal,attributes"]
44 | ----
45 | $ *kubectl get deployments*
46 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
47 | frontend-ui 2 2 2 2 3h
48 | guestbook-service 1 1 1 1 2h
49 | helloworld-service-vertx 6 6 6 6 2h
50 | mysql 1 1 1 1 2h
51 |
52 | $ *kubectl get pods*
53 | NAME READY STATUS RESTARTS AGE
54 | frontend-ui-2676544744-3k1p6 1/1 Running 0 3h
55 | frontend-ui-2676544744-b88hg 1/1 Running 0 3h
56 | guestbook-service-114023015-8x9j8 1/1 Running 0 2h
57 | helloworld-service-vertx-3644252884-73cxk 1/1 Running 0 48s
58 | helloworld-service-vertx-3644252884-t364t 1/1 Running 0 2h
59 | helloworld-service-vertx-3644252884-v5t67 1/1 Running 0 48s
60 | helloworld-service-vertx-3644252884-wct43 1/1 Running 0 48s
61 | helloworld-service-vertx-3644252884-x7ggl 1/1 Running 0 48s
62 | helloworld-service-vertx-3644252884-xxvzh 1/1 Running 0 2h
63 | mysql-471477625-rnjt1 1/1 Running 0 2h
64 | ----
65 |
66 | Reduce the number of replicas back to 2 so that we can free up resources for the later labs:
67 |
68 | [source, bash, subs="normal,attributes"]
69 | ----
70 | $ *kubectl scale deployment helloworld-service-vertx --replicas=2*
71 | deployment "helloworld-service-vertx" scaled
72 | ----
73 |
--------------------------------------------------------------------------------
/frontend/index.html:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | Microservices Frontend
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
46 |
47 |
48 |
49 |
50 |
51 |
Say Hi - Version 2
52 |
77 |
78 |
79 |
Sample hello message
80 |
81 |
82 |
83 |
85 |
86 |
87 |
Name
88 |
Message
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/lab/app-frontend-deployment.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Deploy frontend
17 | Duration: 5:00
18 |
19 | A Kubernetes pod is a group of containers, tied together for the purposes of administration and networking. It can contain one or more containers. All containers within a single pod will share the same networking interface, IP address, volumes, etc. All containers within the same pod instance will live and die together. It’s especially useful when you have, for example, a container that runs the application, and another container that periodically polls logs/metrics from the application container.
20 |
21 | You can start a single Pod in Kubernetes by creating a Pod resource. However, a Pod created this way would be known as a link:https://kubernetes.io/docs/concepts/configuration/overview/#naked-pods-vs-replication-controllers-and-jobs[Naked Pod]. However, if a Naked Pod dies/exits, it will not be restarted by Kubernetes. A better way to start a pod, is by using a higher-level construct such as Replication Controller, Replica Set, or a Deployment.
22 |
23 | A Replication Controller ensures that a specified number of pod "replicas" are running. If there are too many pods, it will kill some. If there are too few, the replication controller will start more. Unlike manually created pods, the pods maintained by a replication controller are automatically replaced if they fail, get deleted, or are terminated.
24 |
25 | A Deployment provides declarative updates for Pods and Replication Controllers. You only need to describe the desired state in a Deployment object, and the Deployment controller will change the actual state to the desired state at a controlled rate for you. You can use deployments to easily:
26 | - Create a Deployment to bring up a Replication Controller and Pods.
27 | - Check the status of a Deployment to see if it succeeds or not.
28 | - Later, update that Deployment to recreate the Pods (for example, to use a new image, or configuration).
29 | - Rollback to an earlier Deployment revision if the current Deployment isn’t stable.
30 | - Pause and resume a Deployment.
31 |
32 | In this lab, because we are working with Kubernetes 1.2+, we will be using Deployment extensively.
33 |
34 | First create a Deployment using kubectl, the Kubernetes CLI tool:
35 |
36 | [source, bash, subs="normal,attributes"]
37 | ----
38 | $ *kubectl create -f frontend-deployment.yaml*
39 | deployment.extensions/frontend-ui created
40 | ----
41 |
42 | You should see the frontend instances running:
43 |
44 | [source, bash, subs="normal,attributes"]
45 | ----
46 | $ *kubectl get pods -w*
47 | NAME READY STATUS RESTARTS AGE
48 | frontend-ui-????? 0/1 ContainerCreating 0 2m
49 | frontend-ui-????? 1/1 Running 0 2m
50 | ----
51 |
52 | Hit CTRL+C to exit back to the shell prompt at any moment.
53 |
54 | NOTE: The _ContainerCreating_ status means that Kubernetes still downloading the image from the registry before creating the containers.
55 |
56 |
--------------------------------------------------------------------------------
/lab/health-checks.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Health Checks
17 | Duration: 10:00
18 |
19 | During rolling update, a pod is removed as soon as a newer version of pod is up and ready to serve. By default, without health checks, Kubernetes will route traffic to the new pod as soon as the pods starts. But, it's most likely that your application will take sometime to start, and if you route traffic to the application that isn't ready to serve, your users (and/or consuming services) will see errors. To avoid this, Kubernetes comes with two types of checks: Liveness Probe, and Readiness Probe.
20 |
21 | After a container starts, it is not marked as Healthy until the Liveness Probe succeeds. However, if the number of Liveness Probe failures exceeds a configurable failure threshold, Kubernetes will mark the pod unhealthy and attempt to restart the pod.
22 |
23 | When a pod is Healthy doesn't mean it's ready to serve. You may want to warm up requests/cache, and/or transfer state from other instances. You can further mark when the pod is Ready to serve by using a Readiness Probe.
24 |
25 | Let's add a Liveness Probe to our Helloworld Service by editing the Deployment:
26 |
27 | [source, bash, subs="normal,attributes"]
28 | ----
29 | $ *kubectl edit deployment helloworld-service-vertx*
30 | ----
31 | include::includes/tip.adoc[]
32 |
33 | In the editor, add a Liveness Probe:
34 |
35 | [source, yaml, subs="normal,attributes"]
36 | ----
37 | apiVersion: extensions/v1beta1
38 | kind: Deployment
39 | ...
40 | spec:
41 | ...
42 | template:
43 | ...
44 | spec:
45 | ...
46 | containers:
47 | - image: rafabene/microservices-helloworld-vertx:...
48 | *livenessProbe:
49 | initialDelaySeconds: 5
50 | timeoutSeconds: 1
51 | httpGet:
52 | path: /api/hello/Kubernetes
53 | port: 8080*
54 | ...
55 | ----
56 |
57 | NOTE: You can configure both Liveness Probe and Readiness Probe by checking via a HTTP GET request, a HTTPS GET request, TCP port connectivity, or even a shell script! See the http://kubernetes.io/docs/user-guide/production-pods/#liveness-and-readiness-probes-aka-health-checks[Liveness and Readiness guide] for more information.
58 |
59 | You can add a Readiness Probe in the similar way:
60 |
61 | [source, bash, subs="normal,attributes"]
62 | ----
63 | $ *kubectl edit deployment helloworld-service-vertx*
64 | ----
65 | include::includes/tip.adoc[]
66 |
67 | In the editor, add a Readiness Probe:
68 |
69 | [source, yaml, subs="normal,attributes"]
70 | ----
71 | apiVersion: extensions/v1beta1
72 | kind: Deployment
73 | ...
74 | spec:
75 | ...
76 | template:
77 | ...
78 | spec:
79 | ...
80 | containers:
81 | - image: rafabene/microservices-helloworld-vertx:...
82 | *readinessProbe:
83 | initialDelaySeconds: 5
84 | timeoutSeconds: 1
85 | httpGet:
86 | path: /api/hello/Kubernetes
87 | port: 8080*
88 | ...
89 | ----
90 |
91 | NOTE: In a production scenario, the Liveness Probe and the Readiness Probe will probably be different REST endpoints or scripts.
92 |
--------------------------------------------------------------------------------
/helloworld-service/src/main/java/com/redhat/developers/helloworld/ApplicationConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.redhat.developers.helloworld;
2 |
3 | import java.util.Map;
4 | import java.util.Objects;
5 | import java.util.Properties;
6 |
7 | import io.vertx.core.AbstractVerticle;
8 | import io.vertx.core.json.JsonObject;
9 |
10 | /**
11 | * Just some configuration utilities.
12 | *
13 | * @author Clement Escoffier
14 | */
15 | public class ApplicationConfiguration {
16 |
17 | /**
18 | * Creates a Json Object from the environment variables and system properties.
19 | * The system properties override the environment variables.
20 | *
21 | * @return the json object
22 | */
23 | public static JsonObject load() {
24 | return putAll(
25 | putAll(
26 | new JsonObject(), System.getenv()), System.getProperties()
27 | );
28 | }
29 |
30 | /**
31 | * Creates a Json Object from the given configuration, the environment variables
32 | * and system properties.
33 | * The system properties override the environment variables that override the given json object.
34 | *
35 | * This method is intended to be used with {@link AbstractVerticle#config()}:
36 | * {@code JsonObject json = ApplicationConfiguration.load(config())}
37 | *
38 | * @param json the json object
39 | * @return
40 | */
41 | public static JsonObject load(JsonObject json) {
42 | return putAll(
43 | putAll(
44 | json, System.getenv()), System.getProperties()
45 | );
46 | }
47 |
48 |
49 | /**
50 | * Creates a new json object containing the content of the given json object merged with
51 | * the given Map. The content of the Map overrides the content of the given json object.
52 | *
53 | * @param conf the configuration
54 | * @param props the map
55 | * @return the json object
56 | */
57 | private static JsonObject putAll(JsonObject conf, Map props) {
58 | Objects.requireNonNull(conf);
59 | Objects.requireNonNull(props);
60 | JsonObject json = conf.copy();
61 | props.entrySet().stream().forEach(entry -> put(json, entry.getKey(), entry.getValue()));
62 | return json;
63 | }
64 |
65 | /**
66 | * Creates a new json object containing the content of the given json object merged with
67 | * the given Properties. The content of the Properties overrides the content of the given
68 | * json object.
69 | *
70 | * @param conf the configuration
71 | * @param props the map
72 | * @return the json object
73 | */
74 | private static JsonObject putAll(JsonObject conf, Properties props) {
75 | Objects.requireNonNull(conf);
76 | Objects.requireNonNull(props);
77 | JsonObject json = conf.copy();
78 | props.stringPropertyNames().stream()
79 | .forEach(name -> put(json, name, props.getProperty(name)));
80 | return json;
81 | }
82 |
83 | private static void put(JsonObject json, String name, String value) {
84 | Objects.requireNonNull(value);
85 | Boolean bool = asBoolean(value);
86 | if (bool != null) {
87 | json.put(name, bool);
88 | } else {
89 | Double integer = asNumber(value);
90 | if (integer != null) {
91 | json.put(name, integer);
92 | } else {
93 | json.put(name, value);
94 | }
95 | }
96 | }
97 |
98 |
99 | private static Double asNumber(String s) {
100 | try {
101 | return Double.parseDouble(s);
102 | } catch (NumberFormatException nfe) {
103 | return null;
104 | }
105 | }
106 |
107 | private static Boolean asBoolean(String s) {
108 | if (s.equalsIgnoreCase("true")) {
109 | return Boolean.TRUE;
110 | } else if (s.equalsIgnoreCase("false")) {
111 | return Boolean.FALSE;
112 | } else {
113 | return null;
114 | }
115 | }
116 |
117 | }
--------------------------------------------------------------------------------
/lab/app-deploy-microservices-networking.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #### Internal Kubernetes networking
17 | Duration: 7:00
18 |
19 | In Kubernetes every pod has a unique IP address! You can “login” into one of these pods by using the _kubectl exec_ command. This can drop you into a shell and execute commands inside of the container.
20 |
21 | First, find the name of the both helloworld-service-vertx pods:
22 |
23 | [source, bash, subs="normal,attributes"]
24 | ----
25 | $ *kubectl get pods -l app=helloworld-service-vertx*
26 | NAME READY STATUS RESTARTS AGE
27 | helloworld-service-vertx-????? 1/1 Running 0 14m
28 | helloworld-service-vertx-????? 1/1 Running 0 15m
29 | ----
30 |
31 | NOTE: Note that we used the parameter _-l app=helloworld-service-vertx_. This parameter allows us to specify labels as filter. The label _app=helloworld-service-vertx_ was defined in the ReplicationController as a template for all pods.
32 |
33 | Then, use _kubectl exec_ to exucute a _"bash"_ process into the container:
34 |
35 | [source, bash, subs="normal,attributes"]
36 | ----
37 | $ *kubectl exec -it helloworld-service-vertx-????? bash*
38 | bash-4.2$ _
39 | ----
40 |
41 | You are now in a shell inside of the helloworld-service-vertx container. You can run _ps_, and _hostname_:
42 |
43 | [source, bash, subs="normal,attributes"]
44 | ----
45 | bash-4.2$ *ps aux*
46 | USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
47 | 1000160+ 1 0.5 0.1 4123640 68904 ? Ssl 19:12 0:01 java -Dvertx.disableFileCPResolving=true -Xmx256m -jar
48 | 1000160+ 44 0.0 0.0 11768 1676 ? Ss 19:13 0:00 bash
49 | 1000160+ 50 0.0 0.0 47420 1668 ? R+ 19:15 0:00 ps aux
50 |
51 | bash-4.2$ *hostname -i*
52 | 10.1.6.3
53 |
54 | bash-4.2$ *exit*
55 | exit
56 | ----
57 |
58 | Don’t forget to exit :).
59 |
60 | [TIP]
61 | ====
62 | You can begin to have a taste of some of the OpenShift enhancements now.
63 | OpenShift Client (oc) allows you to easily access the shell through the command `oc rsh helloworld-service-vertx-?????`
64 | ====
65 |
66 | Try it with another the other pod and see its IP address.
67 |
68 | Since we are running two instances of the Hello World Service (one instance in one pod), and that the IP addresses are not only unique, but also ephemeral - how will a client reach our services? We need a way to discover the service.
69 |
70 | In Kubernetes, Service Discovery is a first class citizen. We created a Service that will:
71 |
72 | - act as a load balancer to load balance the requests to the pods, and
73 | - provide a stable IP address, allow discovery from the API, and also create a DNS name!
74 |
75 | If you login into a container (find and use the frontend-ui container), you can access the helloworldservice via the DNS name:
76 |
77 | [source, bash, subs="normal,attributes"]
78 | ----
79 | $ *kubectl exec -it frontend-ui-????? bash*
80 |
81 | bash-4.2$ *wget -qO- http://helloworld-service-vertx:8080/api/hello/Rafael*
82 | Hello Rafael from helloworld-service-vertx-a4zq3 with 1.0
83 |
84 | bash-4.2$ *exit*
85 | exit
86 | ----
87 |
88 | Pretty simple right!?
89 |
--------------------------------------------------------------------------------
/lab/external-access.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Accessing the frontend
17 | Duration: 5:00
18 |
19 | When we deployed the frontend, we needed to specify that *the service needs to be externally accessible*. In Kubernetes, you can instruct the underlying infrastructure to create an external load balancer, by specifying the Service Type as a _LoadBalancer_.
20 |
21 | You can see it in the frontend-service.yaml:
22 |
23 | [source,yaml,subs="normal,attributes"]
24 | ----
25 | include::../kubernetes/frontend-service.yaml[]
26 | ----
27 |
28 | Kubernetes *ServiceTypes* allow you to specify what kind of service you want. The default and base type is *ClusterIP*, which exposes a service to connection from inside the cluster. *_NodePort_ and _LoadBalancer_ are two types that expose services to external traffic*.
29 |
30 | Valid values for the ServiceType field are:
31 |
32 | - *ClusterIP*: use a cluster-internal IP only - this is the default and is discussed above. Choosing this value means that you want this service to be reachable only from inside of the cluster.
33 | - *NodePort*: on top of having a cluster-internal IP, expose the service on a port on each node of the cluster (the same port on each node). You’ll be able to contact the service on any :NodePort address.
34 | - *LoadBalancer*: on top of having a cluster-internal IP and exposing service on a NodePort also, ask the cloud provider for a load balancer which forwards to the Service exposed as a :NodePort for each Node.
35 |
36 | Note that we have specified *LoadBalancer*, but it only works on cloud providers which support external load balancers. For example, in Google Cloud Platform (GCE), a load balancer will be created asynchronously and a new external ip will be assigned. The external ip address would be available under the field *LoadBalancer Ingress*. Example:
37 |
38 | [source, bash, subs="normal,attributes"]
39 | ----
40 | $ *kubectl describe service frontend-ui*
41 | Name: frontend-ui
42 | Namespace: myproject
43 | Labels: app=frontend-ui
44 | lab=kubernetes-lab
45 | Annotations:
46 | Selector: app=frontend-ui
47 | Type: LoadBalancer
48 | IP: 172.30.40.241
49 | External IPs: 172.29.133.81
50 | *LoadBalancer Ingress: 172.29.133.81*
51 | Port: http-80 80/TCP
52 | *NodePort: http-80 3????/TCP&
53 | Endpoints: 172.17.0.3:8080,172.17.0.4:8080
54 | Session Affinity: None
55 | Events:
56 | ----
57 |
58 | IMPORTANT: Since CDK doesn't support the creation of external LoadBalancers, you can access the service through the *NodePort*. Kubernetes allocates a port _(default: 30000-32767)_, and each Node in the cluster will proxy that port (the same port number on every Node) into the frontend PODs. Later, in this lab, you will learn an alternative to *NodePorts* and *LoadBalancer*.
59 |
60 | First, execute *kubectl describe services frontend-ui* and find out which port (between: 30000-32767) Kubernetes assigned in the OpenShift node. Once that you have the NodePort, you can access the guestbook via the cluster address and port number by navigating the browser to http://master.xpto.com.br:/.
61 |
62 | Example: http://{ocp-cluster}:31079/
63 |
64 | NOTE: The NodePort (31079) is a random value. You should use the value described in NodePort via _kubectl describe service frontend-service_. The IP is the external ip of the Kubernetes Cluster
65 |
66 | You should see something like this:
67 |
68 |
69 | image::images/app-screenshot.png[App Screenshot,float="center",align="center"]
70 |
--------------------------------------------------------------------------------
/helloworld-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 | 4.0.0
20 |
21 | com.redhat.developers.helloworld
22 | helloworld-service
23 | jar
24 | 0.0.1-SNAPSHOT
25 | hellworld-service
26 |
27 | https://developers.redhat.com/
28 |
29 |
30 |
31 | Apache License, Version 2.0
32 | repo
33 | http://www.apache.org/licenses/LICENSE-2.0.html
34 |
35 |
36 |
37 |
38 |
40 |
42 | UTF-8
43 |
44 | io.vertx.core.Launcher
45 | com.redhat.developers.helloworld.HelloworldVerticle
46 |
47 |
48 | 1.8
49 | 1.8
50 |
51 |
52 | 1.4.0
53 | 3.2.1
54 |
55 |
56 |
57 |
58 |
59 | io.vertx
60 | vertx-core
61 | ${vertx.version}
62 |
63 |
64 | io.vertx
65 | vertx-web
66 | ${vertx.version}
67 |
68 |
69 | org.apache.commons
70 | commons-lang3
71 | 3.4
72 |
73 |
74 |
75 |
76 | helloworld-service
77 |
78 |
79 | org.codehaus.mojo
80 | exec-maven-plugin
81 | ${version.exec.plugin}
82 |
83 | ${java.main.class}
84 |
85 | run
86 | ${vertx.main.verticle}
87 | -conf
88 | config.json
89 |
90 |
91 |
92 |
93 | org.apache.maven.plugins
94 | maven-shade-plugin
95 | 2.4.3
96 |
97 |
98 | package
99 |
100 | shade
101 |
102 |
103 |
104 |
106 |
107 | ${java.main.class}
108 | ${vertx.main.verticle}
109 |
110 |
111 |
112 | ${project.build.directory}/${project.artifactId}-fat.jar
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/lab/app-deploy-microservices.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Deploy Microservices
17 | Duration: 5:00
18 |
19 | As mentioned before, the application makes use of two other microservices:
20 |
21 | - the Guestbook service (that writes to the MySQL database)
22 | - a Hello World service
23 |
24 | Both services are containers whose images contain self-executing JAR files. The sources are available in the git repository if you are interested in seeing it.
25 |
26 | When deploying these microservices instances, we want to make sure that:
27 |
28 | * We can scale the number of instances once deployed.
29 | * If any of the instances becomes unhealthy and/or fails, we want to make sure they are restarted automatically.
30 |
31 | Let’s deploy the microservices one at a time:
32 |
33 | First, deploy the Hello World:
34 |
35 | [source, bash, subs="normal,attributes"]
36 | ----
37 | $ *kubectl create -f helloworldservice-deployment.yaml -f helloworldservice-service.yaml*
38 | deployment.extensions/helloworld-service-vertx created
39 | service/helloworld-service-vertx created
40 | ----
41 |
42 | Once created, you can see the replicas with:
43 |
44 | [source, bash, subs="normal,attributes"]
45 | ----
46 | $ *kubectl get deployments*
47 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
48 | frontend-ui 2 2 2 2 12m
49 | helloworld-service-vertx 2 2 2 2 22s
50 | mysql 1 1 1 1 3m
51 | ----
52 |
53 | You can see the pods running:
54 |
55 | [source, bash, subs="normal,attributes"]
56 | ----
57 | $ *kubectl get pods*
58 | NAME READY STATUS RESTARTS AGE
59 | frontend-ui-1bvcv 1/1 Running 0 2h
60 | frontend-ui-5vtsp 1/1 Running 0 2h
61 | helloworld-service-vertx-prnhv 1/1 Running 0 4m
62 | helloworld-service-vertx-sgds6 1/1 Running 0 4m
63 | mysql-xvi3c 1/1 Running 0 1h
64 | ----
65 |
66 | You can also look at each pod’s log output by running:
67 |
68 | [source, bash, subs="normal,attributes"]
69 | ----
70 | $ *kubectl logs -f helloworld-service-vertx-?????*
71 | Aug 02, 2016 5:38:11 AM io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
72 | INFO: Succeeded in deploying verticle
73 | ----
74 | *Note:* The _-f_ flag tails the log. To stop tailing, press _Ctrl+C_.
75 |
76 | Our descriptor file specified 2 replicas. So, if you delete one of the pods (and now you only have 1 replica rather than 2), the ReplicationController will notice that and start another pod for you to meet the configured 2 replicas specification. Let's try it!
77 |
78 | [source, bash, subs="normal,attributes"]
79 | ----
80 | $ *kubectl delete pod helloworld-service-vertx-?????*
81 | pod "helloworld-service-vertx-????" deleted
82 | ----
83 |
84 | You should see that the pod was deleted, and the ReplicationController will ensure a second instance is started. Sometimes this goes by very fast - and you'll notice that the pod you deleted is no longer there, and another pod, with a different name, was started.
85 |
86 | [source, bash, subs="normal,attributes"]
87 | ----
88 | $ *kubectl get pods*
89 | NAME READY STATUS RESTARTS AGE
90 | ...
91 | helloworld-service-vertx-ezuq3 1/1 Running 0 1m
92 | helloworld-service-vertx-sgds6 1/1 Running 0 10m
93 | ...
94 | ----
95 |
96 | Lastly, let’s create the Guestbook Service replication controller and service too!
97 |
98 | [source, bash, subs="normal,attributes"]
99 | ----
100 | $ *kubectl create -f guestbookservice-deployment.yaml -f guestbookservice-service.yaml*
101 | deployment "guestbook-service" created
102 | service "guestbook-service" created
103 | ----
104 |
105 | include::app-deploy-microservices-networking.adoc[]
106 |
--------------------------------------------------------------------------------
/guestbook-service/src/main/java/com/redhat/developers/guestbook/rest/BadwordFilter.java:
--------------------------------------------------------------------------------
1 | package com.redhat.developers.guestbook.rest;
2 |
3 | import javax.annotation.PostConstruct;
4 | import javax.inject.Singleton;
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStreamReader;
8 | import java.net.URL;
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | @Singleton
14 | public class BadwordFilter {
15 |
16 | static Map words = new HashMap<>();
17 | static int largestWordLength = 0;
18 |
19 | @PostConstruct
20 | public void loadConfigs() {
21 | try {
22 | BufferedReader reader = new BufferedReader(new InputStreamReader(new URL("https://docs.google.com/spreadsheets/d/1hIEi2YG3ydav1E06Bzf2mQbGZ12kh2fe4ISgLg_UBuM/export?format=csv").openConnection().getInputStream()));
23 | String line = "";
24 | int counter = 0;
25 | while((line = reader.readLine()) != null) {
26 | counter++;
27 | String[] content = null;
28 | try {
29 | content = line.split(",");
30 | if(content.length == 0) {
31 | continue;
32 | }
33 | String word = content[0];
34 | String[] ignore_in_combination_with_words = new String[]{};
35 | if(content.length > 1) {
36 | ignore_in_combination_with_words = content[1].split("_");
37 | }
38 |
39 | if(word.length() > largestWordLength) {
40 | largestWordLength = word.length();
41 | }
42 | words.put(word.replaceAll(" ", ""), ignore_in_combination_with_words);
43 |
44 | } catch(Exception e) {
45 | e.printStackTrace();
46 | }
47 |
48 | }
49 | System.out.println("Loaded " + counter + " words to filter out");
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 |
54 | }
55 |
56 |
57 | /**
58 | * Iterates over a String input and checks whether a cuss word was found in a list, then checks if the word should be ignored (e.g. bass contains the word *ss).
59 | * @param input
60 | * @return
61 | */
62 | public ArrayList badWordsFound(String input) {
63 | if(input == null) {
64 | return new ArrayList<>();
65 | }
66 |
67 | // remove leetspeak
68 | input = input.replaceAll("1","i");
69 | input = input.replaceAll("!","i");
70 | input = input.replaceAll("3","e");
71 | input = input.replaceAll("4","a");
72 | input = input.replaceAll("@","a");
73 | input = input.replaceAll("5","s");
74 | input = input.replaceAll("7","t");
75 | input = input.replaceAll("0","o");
76 | input = input.replaceAll("9","g");
77 |
78 | ArrayList badWords = new ArrayList<>();
79 | input = input.toLowerCase().replaceAll("[^a-zA-Z]", "");
80 |
81 | // iterate over each letter in the word
82 | for(int start = 0; start < input.length(); start++) {
83 | // from each letter, keep going to find bad words until either the end of the sentence is reached, or the max word length is reached.
84 | for(int offset = 1; offset < (input.length()+1 - start) && offset < largestWordLength; offset++) {
85 | String wordToCheck = input.substring(start, start + offset);
86 | if(words.containsKey(wordToCheck)) {
87 | // for example, if you want to say the word bass, that should be possible.
88 | String[] ignoreCheck = words.get(wordToCheck);
89 | boolean ignore = false;
90 | for(int s = 0; s < ignoreCheck.length; s++ ) {
91 | if(input.contains(ignoreCheck[s])) {
92 | ignore = true;
93 | break;
94 | }
95 | }
96 | if(!ignore) {
97 | badWords.add(wordToCheck);
98 | }
99 | }
100 | }
101 | }
102 |
103 |
104 | return badWords;
105 |
106 | }
107 |
108 |
109 | public String filterText(String input) {
110 | ArrayList badWords = badWordsFound(input);
111 | if(badWords.size() > 0) {
112 | return "This message was blocked because a bad word was found. If you believe this word should not be blocked, please message support.";
113 | }
114 | return input;
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/lab/configuring-configmap.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | #### Using ConfigMap
17 |
18 | In this section, we'll use Kubernetes 1.2's new feature, ConfigMap, to configure the application. You can store multiple string-based configuration files inside of a single ConfigMap configuration. In our example, we'll store Vert.x's config.json into a ConfigMap entry.
19 |
20 | First, update the _kubernetes-lab/hellworld-service/config.json_ with a new configuration value:
21 | [source, bash, subs="normal,attributes"]
22 | ----
23 | $ *cd kubernetes-lab/hellworld-service/*
24 | $ *vi config.json*
25 | ----
26 | include::includes/tip.adoc[]
27 |
28 | Here is a suggestion for you:
29 |
30 | [source, json, subs="normal,attributes"]
31 | ----
32 | {
33 | "GREETING": "Hello {name} from ConfigMap"
34 | }
35 | ----
36 |
37 | Next, create a ConfigMap entry with this file:
38 |
39 | [source, bash, subs="normal,attributes"]
40 | ----
41 | $ *oc create configmap greeting-config --from-file=config.json*
42 | configmap "greeting-config" created
43 | ----
44 |
45 | Let's take a look inside the newly created entry:
46 |
47 | [source, bash, subs="normal,attributes"]
48 | ----
49 | $ *oc edit configmap greeting-config*
50 | # HINT: Type ':wq' to exit from vi
51 | ----
52 |
53 | You'll see that the _config.json_ is now part of the YAML file:
54 |
55 | [source, yaml, subs="normal,attributes"]
56 | ----
57 | apiVersion: v1
58 | data:
59 | *config.json: |
60 | {
61 | "GREETING": "Hello {name} from ConfigMap"
62 | }*
63 | kind: ConfigMap
64 | ...
65 | ----
66 |
67 | You can, of course, edit this ConfigMap in the editor too. If you do, edit only the value for the greeting variable.
68 |
69 | There are several ways to access the values in this ConfigMap:
70 |
71 | * Mount the entries (in our case, config.json) as a file.
72 | * Access from the Kubernetes API (we won't cover this today).
73 |
74 | Let's see how we can mount the configurations as files under a specific directory, e.g., _/etc/config/config.json_.
75 |
76 | First, edit the Helloworld Service Deployment:
77 |
78 | [source, bash, subs="normal,attributes"]
79 | ----
80 | $ *oc edit deployment helloworld-service-vertx*
81 | ----
82 | include::includes/tip.adoc[]
83 |
84 | In the editor, add volumes and volume mounts (important - indentation matters!):
85 |
86 | [source,yaml, subs="normal,attributes"]
87 | ----
88 | apiVersion: v1
89 | kind: DeploymentConfig
90 | ...
91 | spec:
92 | ...
93 | template:
94 | ...
95 | spec:
96 | *volumes:
97 | - name: config-volume
98 | configMap:
99 | name: greeting-config*
100 | containers:
101 | - image: rafabene/microservices-helloworld-vertx:1.0
102 | *volumeMounts:
103 | - name: config-volume
104 | mountPath: /etc/config*
105 | ...
106 | ----
107 |
108 | This will make the configuration file available as the file _/etc/config/config.json_. Let's verify by going into the pod itself (remember how to do this by using _kubectl exec_? You can also use _oc exec_, but now you will learn another option: _oc rsh_):
109 |
110 | First, find the pod name:
111 |
112 | [source, bash, subs="normal,attributes"]
113 | ----
114 | $ *oc get pods*
115 | NAME READY STATUS RESTARTS AGE
116 | ...
117 | helloworld-service-vertx-7-e1o5u 1/1 Running 0 54s
118 | helloworld-service-vertx-7-sgosp 1/1 Running 0 40s
119 | ...
120 | ----
121 |
122 | Then, run a shell inside the pod, and see what's in _/etc/config_:
123 |
124 | [source,bash, subs="normal,attributes"]
125 | ----
126 | $ *oc rsh helloworld-service-vertx-7-?????*
127 |
128 | sh-4.2$ *ls /etc/config/*
129 | config.json
130 |
131 | sh-4.2$ *cat /etc/config/config.json*
132 | {
133 | "GREETING": "Hello {name} from ConfigMap"
134 | }
135 |
136 | sh-4.2$ *exit*
137 | exit
138 | ----
139 |
140 | NOTE: Don't forget to exit out of the pod environment!
141 |
142 | Great, the file is there, but the application needs to be configured to reference to the file. Vert.x can reference to an external configuration with the command line argument:
143 |
144 | [source,subs="normal,attributes"]
145 | ----
146 | -conf /etc/config/config.json
147 | ----
148 |
149 | Recall how you were able to configure the command line arguments in the previous steps. You know the drill. Edit the Helloworld Service Deployment and add the arguments:
150 |
151 | [source,yaml, subs="normal,attributes"]
152 | ----
153 | apiVersion: extensions/v1beta1
154 | kind: Deployment
155 | ...
156 | spec:
157 | ...
158 | template:
159 | ...
160 | spec:
161 | ...
162 | containers:
163 | - image: rafabene/microservices-helloworld-vertx:...
164 | *args:
165 | - -conf
166 | - /etc/config/config.json*
167 | ...
168 | ----
169 |
170 | Check the application to see it is using the new greeting string.
171 |
172 | Last, but not least, you can also specify simple key/value pairs in ConfigMap, and then expose them directly as environmental variables too. See the http://kubernetes.io/docs/user-guide/configmap/[ConfigMap guide] for more examples.
173 |
--------------------------------------------------------------------------------
/lab/managing-credentials.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### Managing Credentials
17 | Duration: 20:00
18 |
19 | ConfigMap is great to store text-based configurations. Depending on your use cases, it may not be the best place to store your credentials (which sometimes may be a binary file rather than text). Secrets can be used to hold sensitive information, such as passwords, OAuth tokens, and SSH keys. Entries in Secrets are Base64 encoded. However, Secrets are not additionally encrypted when stored in Kubernetes.
20 |
21 | In this section, we'll create a Secret that contains the MySQL username and password. We'll subsequently update both the MySQL Replication Controller and the Guestbook Service to refer to the same credentials.
22 |
23 | First, let's create a Secret with username and password the command line:
24 |
25 | [source, bash, subs="normal,attributes"]
26 | ----
27 | $ *oc create secret generic mysql-secret \
28 | --from-literal=username=app,password=1337*
29 | secret "mysql-secret" created
30 | ----
31 |
32 | If you look into the newly created Secret, you'll see that the values are Base64 encoded:
33 |
34 | [source, bash, subs="normal,attributes"]
35 | ----
36 | $ *oc edit secret mysql-secret*
37 | # HINT: Type ':wq' to exit from vi
38 | ----
39 |
40 | In the Editor, you'll see:
41 |
42 | [source, yaml, subs="normal,attributes"]
43 | ----
44 | apiVersion: v1
45 | data:
46 | password: MTMzNw==
47 | username: YXBw
48 | kind: Secret
49 | ...
50 | ----
51 |
52 | In the pods, you can access these values a couple of ways:
53 |
54 | * Mount each entry as a file under a directory (similar to what we did with ConfigMap)
55 | * Use http://kubernetes.io/docs/user-guide/downward-api/#exposing-pod-information-into-a-container[Downward API] to expose each entry as an Environmental Variable (which you can also do with ConfigMap).
56 |
57 | Since the MySQL container already expects username and password to be configured using the Environmental Variables, we'll use the latter (Downward API) approach.
58 |
59 | First, in kubernetes/ directory, edit the mysql-deployment.yaml. Edit the mysql Deployment and modify the variables MYSQL_USER and MYSQL_PASSWORD with the following values:
60 |
61 | [source, yaml, subs="normal,attributes"]
62 | ----
63 | apiVersion: extensions/v1beta1
64 | kind: Deployment
65 | metadata:
66 | name: mysql
67 | spec:
68 | ...
69 | template:
70 | spec:
71 | containers:
72 | - resources:
73 | ...
74 | env:
75 | - name: MYSQL_ROOT_PASSWORD
76 | value: yourpassword
77 | - name: MYSQL_DATABASE
78 | value: guestbook
79 | *- name: MYSQL_USER
80 | valueFrom:
81 | secretKeyRef:
82 | name: mysql-secret
83 | key: username
84 | - name: MYSQL_PASSWORD
85 | valueFrom:
86 | secretKeyRef:
87 | name: mysql-secret
88 | key: password*
89 | ...
90 | ----
91 |
92 | We'll also need to recreate the *PersistentVolumeClaim* too in order to force MySQL to create the user):
93 |
94 | [source, bash, subs="normal,attributes"]
95 | ----
96 | $ *oc delete pvc/mysql-pvc deployment/mysql*
97 | persistentvolumeclaim "mysql-pvc" deleted
98 | replicationcontroller "mysql" deleted
99 |
100 | $ *oc create -f mysql-pvc.yaml -f mysql-deployment.yaml*
101 | persistentvolumeclaim "mysql-pvc" created
102 | deployment "mysql" created
103 | ----
104 |
105 | Once MySQL comes back up, test the connection by running MySQL client directly inside the pod. Recall how you can use _oc rsh_ to do this:
106 |
107 | [source, bash, subs="normal,attributes"]
108 | ----
109 | $ *oc get pods*
110 | NAME READY STATUS RESTARTS AGE
111 | ...
112 | mysql-... 1/1 Running 0 2m
113 | ...
114 |
115 | $ *oc rsh mysql-...*
116 | sh-4.2$ *mysql -u app -p -h 127.0.0.1*
117 | Enter password: *1337*
118 | Welcome to the MySQL monitor. Commands end with ; or \g.
119 | Your MySQL connection id is 3
120 | Server version: 5.6.24 MySQL Community Server (GPL)
121 |
122 | Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
123 |
124 | Oracle is a registered trademark of Oracle Corporation and/or its
125 | affiliates. Other names may be trademarks of their respective
126 | owners.
127 |
128 | Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
129 |
130 | mysql> *exit*
131 | Bye
132 | sh-4.2$ *exit*
133 | exit
134 | ----
135 |
136 | Great! Now MySQL is picking up the credentials from the Secret.
137 |
138 | Next, configure the Guestbook Service and update the Environmental Variables too.
139 |
140 | Now edit the Guestbook Service deployment and add a couple of environment variables:
141 |
142 | [source, yaml, subs="normal,attributes"]
143 | ----
144 | apiVersion: extensions/v1beta1
145 | kind: Deployment
146 | ...
147 | spec:
148 | ...
149 | template:
150 | ...
151 | spec:
152 | …
153 | containers:
154 | - image: rafabene/microservices-guestbook:1.0
155 | *env:
156 | - name: DATASOURCE_USERNAME
157 | valueFrom:
158 | secretKeyRef:
159 | name: mysql-secret
160 | key: username
161 | - name: DATASOURCE_PASSWORD
162 | valueFrom:
163 | secretKeyRef:
164 | name: mysql-secret
165 | key: password*
166 | ...
167 | ----
168 |
169 | Once the deployment completes, check that the application is still working.
--------------------------------------------------------------------------------
/guestbook-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
20 | 4.0.0
21 |
22 | com.redhat.developers.guestbook
23 | guestbook-service
24 | 0.0.1-SNAPSHOT
25 | war
26 | guestbook
27 | Guestbook microservice running on WildFly Swarm
28 |
29 | https://developers.redhat.com/
30 |
31 |
32 | Apache License, Version 2.0
33 | repo
34 | http://www.apache.org/licenses/LICENSE-2.0.html
35 |
36 |
37 |
38 |
39 |
41 |
43 | UTF-8
44 |
45 |
46 | 1.0.0.Final
47 |
48 |
49 | 1.6.1
50 |
51 |
52 | 2.10
53 | 2.1.1
54 |
55 |
56 | 1.8
57 | 1.8
58 |
59 | 5.1.38
60 |
61 |
62 |
63 |
64 |
65 |
69 |
70 | org.wildfly.swarm
71 | bom
72 | ${version.wildfly.swarm}
73 | pom
74 | import
75 |
76 |
77 | org.apache.deltaspike.distribution
78 | distributions-bom
79 | ${deltaspike.version}
80 | pom
81 | import
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | org.wildfly.swarm
92 | jaxrs-jsonp
93 |
94 |
95 | org.wildfly.swarm
96 | jaxrs-cdi
97 |
98 |
99 | org.wildfly.swarm
100 | datasources
101 |
102 |
103 | org.wildfly.swarm
104 | jpa
105 |
106 |
107 | org.wildfly.swarm
108 | undertow
109 |
110 |
111 |
112 |
113 | org.apache.deltaspike.core
114 | deltaspike-core-api
115 | compile
116 |
117 |
118 |
119 | org.apache.deltaspike.core
120 | deltaspike-core-impl
121 | runtime
122 |
123 |
124 |
125 | org.apache.deltaspike.modules
126 | deltaspike-data-module-api
127 | compile
128 |
129 |
130 |
131 | org.apache.deltaspike.modules
132 | deltaspike-data-module-impl
133 | runtime
134 |
135 |
136 |
137 |
138 |
139 | org.hibernate.javax.persistence
140 | hibernate-jpa-2.1-api
141 | 1.0.0.Final
142 |
143 |
144 |
145 | mysql
146 | mysql-connector-java
147 | ${version.mysql}
148 |
149 |
150 |
151 |
152 |
153 |
155 | ${project.artifactId}
156 |
157 |
158 | src/main/resources
159 | true
160 |
161 |
162 |
163 |
164 | maven-war-plugin
165 | ${version.war.plugin}
166 |
167 |
168 | false
169 |
170 |
171 |
172 |
173 |
174 | org.wildfly.swarm
175 | wildfly-swarm-plugin
176 | ${version.wildfly.swarm}
177 |
178 | com.redhat.developers.guestbook.Main
179 |
180 |
181 |
182 |
183 | package
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/lab/extra.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 |
17 | ## Extra Credit
18 | Duration: 10:00
19 |
20 | Here are some ideas for next steps.
21 |
22 | ### Try OpenShift Source-to-image feature.
23 |
24 | OpenShift allows you to get an Source code and transform it in a container image. This is very useful for people who don't know how to create your own image. OpenShift automatically detects the language and uses an appropriate "builder" to convert that in a functional container image. Actually the following languages are supported: Ruby, JavaEE, NodeJS, PHP, Pytho and Perl.
25 |
26 | Let's see how it works using the link:https://github.com/redhat-developer-demos/kubernetes-lab/tree/master/frontend[frontend sources] as an example:
27 |
28 | First, let's delete the existing frontend *Route*, *Service* and *ReplicationController*
29 |
30 | [source, bash, subs="normal,attributes"]
31 | ----
32 | $ *oc delete deployment,svc,route frontend-ui*
33 | deployment "frontend-ui" deleted
34 | service "frontend-ui" deleted
35 | route "frontend-ui" deleted
36 |
37 | $ *oc new-app --name=frontend-ui \
38 | https://github.com/redhat-developer-demos/kubernetes-lab \
39 | --strategy=source --context-dir=frontend*
40 | --> Found image 0b37bce (5 weeks old) in image stream "openshift/nodejs" under tag "4" for "nodejs"
41 |
42 | Node.js 4
43 | ---------
44 | Platform for building and running Node.js 4 applications
45 |
46 | Tags: builder, nodejs, nodejs4
47 |
48 | * The source repository appears to match: nodejs
49 | * A source build using source code from https://github.com/redhat-developer-demos/kubernetes-lab will be created
50 | * The resulting image will be pushed to image stream "frontend-ui:latest"
51 | * Use 'start-build' to trigger a new build
52 | * This image will be deployed in deployment config "frontend-ui"
53 | * Port 8080/tcp will be load balanced by service "frontend-ui"
54 | * Other containers can access this service through the hostname "frontend-ui"
55 |
56 | --> Creating resources ...
57 | imagestream "frontend-ui" created
58 | buildconfig "frontend-ui" created
59 | deploymentconfig "frontend-ui" created
60 | service "frontend-ui" created
61 | --> Success
62 | Build scheduled, use 'oc logs -f bc/frontend-ui' to track its progress.
63 | Run 'oc status' to view your app.
64 | ----
65 |
66 | This will trigger the build inside OpenShift. You can explore it using the following commands:
67 |
68 | [source, bash, subs="normal,attributes"]
69 | ----
70 | $ *oc get builds*
71 | NAME TYPE FROM STATUS STARTED DURATION
72 | frontend-ui-1 Source Git@e09f71e Running About a minute ago 1m23s
73 |
74 | $ *oc logs -f bc/frontend-ui*
75 | ----
76 |
77 | You can also see the build happening in the OpenShift console:
78 |
79 | image::images/build.png[Build,float="center",align="center"]
80 |
81 | Don't forget to expose the *Route* and try the application. Do you remember how to it, right?
82 |
83 | #### Building a new version.
84 |
85 | When OpenShift is installed in a public address, you can enable link:https://developer.github.com/webhooks/[Github webhooks] that triggers a new OpenShift build each commit. This is useful for Continuous Integration environments. You can read more about it in the following link:https://docs.openshift.com/enterprise/3.2/dev_guide/builds.html#webhook-triggers[guide].
86 |
87 | You can also trigger a new build using *oc start-build * command. It allows you to specify different location for the sources. Try it yourself! Clone the repository or make a local change and run the command.
88 |
89 | Some examples that you can try.
90 |
91 | NOTE: To build from local, you should be in the root path of the kubernetes lab (kubernetes-lab) because you already specified the --context-dir=frontend parameter.
92 |
93 | [source, bash, subs="normal,attributes"]
94 | ----
95 | $ cd kubernetes-lab/
96 | $ *oc start-build frontend-ui \
97 | --from-dir=. \
98 | --follow*
99 | Uploading directory "." as binary input for the build ...
100 | frontend-ui-?
101 | ----
102 |
103 | You can also build from Github sources
104 |
105 | [source, bash, subs="normal,attributes"]
106 | ----
107 | $ *oc start-build frontend-ui \
108 | --git-repository=https://github.com/rafabene/kubernetes-lab \
109 | --follow*
110 | frontend-ui-?
111 | I0804 08:03:45.260863 1 source.go:197] Downloading "https://github.com/redhat-developer-demos/kubernetes-lab" ...
112 | ----
113 |
114 | ### Try some microservices
115 |
116 | link:https://developers.redhat.com/[Red Hat Developers] has worked intensively to integrate different opensource technologies and create a showcase of how cloud-native apps can interact in a microservices architecture: The link:https://github.com/redhat-helloworld-msa/helloworld-msa[Helloworld-MSA] playground!
117 |
118 | This distinct demo allows developers execute some “helloworld” microservices, built using different technologies, and explore the following features:
119 |
120 | - Different implementations: link:http://wildfly-swarm.io/[WildFly Swarm], Spring Boot, link:http://vertx.io/[Vert.X] and link:https://nodejs.org/en/[NodeJS].
121 | - 3 invocation patterns: Browser as a client, link:http://microservices.io/patterns/apigateway.html[API-Gateway], Chained invocation;
122 | - link:http://microservices.io/patterns/service-registry.html[Service-registry], Self-healing, Load-balancing and link:http://blog.christianposta.com/deploy/blue-green-deployments-a-b-testing-and-canary-releases/[Blue/Green deployments] – Provided by link:https://www.openshift.com/[OpenShift];
123 | - JVM Monitoring – Provided by link:https://jolokia.org/[Jolokia];
124 | - Service Monitoring – Provided by link:https://github.com/Netflix/Hystrix/tree/master/hystrix-dashboard[Hystrix Dashboard] via link:https://github.com/fabric8io/kubeflix[Kubeflix];
125 | - Service Tracing – Provided by link:http://zipkin.io/[Zipkin] via link:https://github.com/fabric8io/kubernetes-zipkin[Fabric8’s Kubernetes Zipkin];
126 | - link:https://github.com/Netflix/Hystrix/wiki/Configuration#CommandCircuitBreaker[Circuit breaker] and link:https://github.com/Netflix/Hystrix/wiki/How-To-Use#Fallback[Fallback] – Provided by link:https://github.com/Netflix/Hystrix[Hystrix];
127 | - REST invocation – Provided by link:https://github.com/OpenFeign/feign[Feign] via link:https://github.com/OpenFeign/feign/tree/master/hystrix[HystrixFeign];
128 | - REST API specification – Provided by link:http://swagger.io/[Swagger];
129 | - CI/CD pipelines – Provided by link:https://jenkins.io/[Jenkins] with link:https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin[Pipeline] plugin.
130 |
131 | image::images/helloworldmsa.png[OpenShift,float="center",align="center"]
--------------------------------------------------------------------------------
/lab/openshift.adoc:
--------------------------------------------------------------------------------
1 | // JBoss, Home of Professional Open Source
2 | // Copyright 2016, Red Hat, Inc. and/or its affiliates, and individual
3 | // contributors by the @authors tag. See the copyright.txt in the
4 | // distribution for a full listing of individual contributors.
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 |
16 | ### A console to manage your Kubernetes Cluster
17 | Duration: 10:00
18 |
19 | Until now we have been using Kubernetes CLI (_kubectl_) to manage our cluster. Wouldn't it be good if we could visualize/manage our cluster in a user/interface?
20 |
21 | Let's take a look in OpenShift console.
22 |
23 | NOTE: Don't worry. This is still a Kubernetes lab! OpenShift runs on top of Kubernetes but adds features like deployments, source-to-image, user management, routes, etc.
24 |
25 | Access https://{ocp-cluster}
26 |
27 | [NOTE]
28 | ====
29 | Accept the self-signed HTTPS certificate.
30 |
31 | Login with the credentials:
32 |
33 | - username: *userX*
34 | - password: *openshift*
35 | ====
36 |
37 | Click on *OpenShift sample project* and now you will see all Kubernetes objects that you have created with kubectl command. This happens because OpenShift is built on top of Kubernetes.
38 |
39 | image::images/openshift.png[OpenShift,float="center",align="center"]
40 |
41 | Take some minutes to explore this interface.
42 |
43 | - Click on the Service and Deployment links and see the details.
44 | - Click on the POD number and see the list of PODS. Select one POD to explore.
45 | - Explore the POD details and the other tabs (Environment, Logs, Terminal and Events)
46 | - In the right top corner, click in the gray _Actions_ button and check that you can also edit the YAML file.
47 |
48 | NOTE: The blue bars on top of the pods are "Label filters" that were applied to select just the specific pods for the *ReplicationController* that you clicked.
49 |
50 | image::images/pod.png[Pod,float="center",align="center"]
51 |
52 |
53 | Back to the *Overview* page and check that you can scale up and scale down the number of the pods simply by clicking on the gray arrows on the right hand side of the pods number.
54 |
55 | Let's perform a rolling-update in the shell and see how it behaves visually in OpenShift. Execute the following command and return to the OpenShift console in the browser:
56 |
57 | [source, bash, subs="normal,attributes"]
58 | ----
59 | $ *kubectl set image deployment/frontend-ui frontend-ui=rafabene/microservices-frontend:1.0*
60 | deployment.extensions/frontend-ui image updated
61 | ----
62 |
63 | image::images/rolling-update.png[Rolling Update,float="center",align="center"]
64 |
65 | #### A word about oc command
66 |
67 | You will be introduced now to the _oc_ command. You can think of it as a super set of _kubectl_. You can use it to do almost all operations that you did with _kubectl_. Let's try:
68 |
69 | [source, bash, subs="normal,attributes"]
70 | ----
71 | $ *oc get pods*
72 | NAME READY STATUS RESTARTS AGE
73 | frontend-ui-anbox 1/1 Running 0 1h
74 | frontend-ui-l7jbo 1/1 Running 0 1h
75 | guestbook-service-h4fvr 1/1 Running 0 1h
76 | helloworld-service-vertx-1-738ux 1/1 Running 0 5m
77 | mysql-yhl82 1/1 Running 0 1h
78 |
79 | $ *oc get deployments*
80 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
81 | frontend-ui 2 2 2 2 36m
82 | guestbook-service 1 1 1 1 30m
83 | helloworld-service-vertx 2 2 2 2 32m
84 | mysql 1 1 1 1 33m
85 |
86 | $ *oc get service*
87 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
88 | frontend-ui LoadBalancer 172.30.58.95 172.29.26.18,172.29.26.18 80:31391/TCP 35m
89 | guestbook-service ClusterIP 172.30.205.209 8080/TCP 30m
90 | helloworld-service-vertx ClusterIP 172.30.9.65 8080/TCP 33m
91 | mysql ClusterIP 172.30.240.203 3306/TCP 33m
92 |
93 | $ *oc describe service frontend-ui*
94 | Name: frontend-ui
95 | Namespace: sample-project
96 | Labels: app=frontend-ui,lab=kubernetes-lab
97 | Selector: app=frontend-ui
98 | Type: LoadBalancer
99 | IP: 172.30.212.103
100 | Port: http-80 80/TCP
101 | NodePort: http-80 32186/TCP
102 | Endpoints: 172.17.0.2:8080,172.17.0.5:8080
103 | Session Affinity: None
104 | No events.
105 |
106 | $ *oc delete pod frontend-ui-?????*
107 | pod "frontend-ui-?????" deleted
108 | ----
109 |
110 | Now let's use _oc_ to:
111 |
112 | - Easily set a ReadinessProbe.
113 |
114 |
115 | To create a *ReadinessProbe* with _oc_ command, execute:
116 |
117 | [source, bash, subs="normal,attributes"]
118 | ----
119 | $ *oc set probe deployment helloworld-service-vertx --readiness --get-url=http://:8080/api/hello/Kubernetes*
120 | deployment "helloworld-service-vertx" updated
121 | ----
122 |
123 | This was much easier than the previous time, right?
124 | You can use _oc get deployment helloworld-service-vertx -o yaml_ to see the configuration inside the *DeploymentConfig* object.
125 |
126 | TIP: You can also use *oc set probe deployment helloworld-service-vertx --readiness --remove* to remove the *ReadinessProbe* using *oc* command.
127 |
128 | - Create a route to frontend-ui.
129 |
130 | Now let's create a route and expose the service. But first let's understand what is a *Route*.
131 | Remember that we needed to execute *kubectl describe service frontend-ui* to get the *NodePort*?
132 | A *Route* uses the port 80 of OpenShift and "routes" the requests based on the defined hostname.
133 | Let's see how it works. Execute:
134 |
135 | [source, bash, subs="normal,attributes"]
136 | ----
137 |
138 | $ *oc expose service frontend-ui*
139 | route "frontend-ui" exposed
140 |
141 | $ *oc get routes*
142 | NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
143 | frontend-ui frontend-ui-labX.apps.boston.openshiftworkshop.com frontend-ui http-80 None
144 | ----
145 |
146 |
147 | [source, bash, subs="normal,attributes"]
148 | ----
149 | Now point your browser to the route http://frontend-ui-labX.{app-domain}
150 | ----
151 |
152 | Amazing, right?
153 |
154 | TIP: You can delete the *Route* with the command: *oc delete route frontend-ui*
155 |
156 | [NOTE]
157 | ====
158 | *How frontend.10.1.2.2.nip.io resolved to 10.1.2.2?*
159 |
160 | link:http://www.nip.io/[NIP.IO] allows you to map any IP Address in the following DNS wildcard entries:
161 |
162 | - 10.0.0.1.nip.io maps to 10.0.0.1
163 | - app.10.0.0.1.nip.io maps to 10.0.0.1
164 | - customer1.app.10.0.0.1.nip.io maps to 10.0.0.1
165 | - customer2.app.10.0.0.1.nip.io maps to 10.0.0.1
166 | - otherapp.10.0.0.1.nip.io maps to 10.0.0.1
167 |
168 | NIP.IO maps *.*.nip.io to the corresponding **, even 127.0.0.1.nip.io maps to 127.0.0.1
169 | ====
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------