├── .gitignore ├── LICENSE ├── app-memory ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── aws │ └── samples │ └── memory │ └── MyClass.java ├── app ├── Dockerfile ├── Dockerfile.jre ├── app.yaml ├── greeting-deployment.yaml ├── greeting-service.yaml ├── pom.xml ├── skaffold.yaml └── src │ └── main │ └── java │ └── org │ └── aws │ └── samples │ └── greeting │ ├── Application.java │ └── GreetingController.java ├── buildspec.yml ├── images ├── codepipeline-status.png ├── codepipeline-template.png ├── docker-debug1.png ├── docker-debug2.png ├── docker-debug3.png ├── istio-dag.png ├── istio-dashboard.png ├── jenkinsx-github-token.png └── jenkinsx-log.txt ├── manifests ├── app-hello-howdy.yaml ├── app-ingress.yaml ├── app.yaml ├── appmesh │ ├── app-hello-howdy.yaml │ ├── mesh.yaml │ ├── services.yaml │ ├── virtualnodes.yaml │ └── virtualservice.yaml ├── greeting-pipeline.yaml ├── istio │ ├── app-canary.yaml │ ├── app-rule-75-25.yaml │ └── greeting-delay.yaml ├── kubemonkey │ ├── app-kube-monkey.yaml │ ├── kube-monkey-configmap.yaml │ └── kube-monkey-deployment.yaml └── myapp │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── greeting-deployment.yaml │ └── greeting-service.yaml │ └── values.yaml └── readme.adoc /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.idea 2 | **/target 3 | **/*.iml 4 | **/audit.log 5 | **/m2.tar.gz 6 | 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app-memory/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | org.aws.samples.memory 5 | app-memory 6 | 1.0-SNAPSHOT 7 | jar 8 | 9 | arungupta 10 | latest 11 | ${docker.repo}/${project.build.finalName}:${docker.tag} 12 | UTF-8 13 | 1.8 14 | 1.8 15 | 1 16 | 1024 17 | 1024 18 | 19 | 20 | 21 | ${project.artifactId} 22 | 23 | 24 | org.codehaus.mojo 25 | exec-maven-plugin 26 | 1.6.0 27 | 28 | java 29 | 30 | -Xms${xms}m 31 | -Xmx${xmx}m 32 | -classpath 33 | 34 | ${project.groupId}.MyClass 35 | ${gigabytes} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | jib 45 | 46 | 47 | 48 | com.google.cloud.tools 49 | jib-maven-plugin 50 | 1.3.0 51 | 52 | 53 | openjdk:8u102-jre 54 | 55 | 56 | ${docker.name} 57 | 58 | 59 | true 60 | 61 | 62 | 63 | 64 | 65 | package 66 | 67 | dockerBuild 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app-memory/src/main/java/org/aws/samples/memory/MyClass.java: -------------------------------------------------------------------------------- 1 | package org.aws.samples.memory; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author argu 7 | */ 8 | public class MyClass { 9 | private static final int KILOBYTE = 1024; 10 | private static final int MEGABYTE = KILOBYTE * KILOBYTE; 11 | private static final int GIGABYTE = MEGABYTE * KILOBYTE; 12 | 13 | public static void main(String[] args) { 14 | printStats(); 15 | 16 | byte[] array; 17 | byte[] array2; 18 | byte[] array3; 19 | 20 | if (args.length == 1) { 21 | byte bytes = Byte.parseByte(args[0]); 22 | if (bytes >= 1) { 23 | array = new byte[GIGABYTE]; 24 | Arrays.fill(array, (byte)1); 25 | System.out.println("==> Array1 initialized"); 26 | } 27 | 28 | if (bytes >= 2) { 29 | array2 = new byte[GIGABYTE]; 30 | Arrays.fill(array2, (byte)2); 31 | System.out.println("==> Array2 initialized"); 32 | } 33 | 34 | if (bytes >= 3) { 35 | array3 = new byte[GIGABYTE]; 36 | Arrays.fill(array3, (byte)3); 37 | System.out.println("==> Array3 initialized"); 38 | } 39 | } else { 40 | System.out.println("==> No arrays initialized"); 41 | } 42 | 43 | printStats(); 44 | 45 | array = null; 46 | array2 = null; 47 | array3 = null; 48 | System.out.println("==> Array nullified"); 49 | 50 | Runtime.getRuntime().gc(); 51 | System.out.println("==> GC done"); 52 | 53 | printStats(); 54 | 55 | } 56 | 57 | static private void printStats() { 58 | System.out.println("** PROCESSOR AND MEMORY STATS **"); 59 | Runtime rt = Runtime.getRuntime(); 60 | System.out.println("processors: " + rt.availableProcessors()); 61 | System.out.println("max memory: " + printUnits(rt.maxMemory())); 62 | System.out.println("free memory: " + printUnits(rt.freeMemory())); 63 | System.out.println("total memory: " + printUnits(rt.totalMemory())); 64 | System.out.println("** PROCESSOR AND MEMORY STATS **"); 65 | } 66 | 67 | static private String printUnits(long bytes) { 68 | int unit = 1024; 69 | if (bytes < unit) { 70 | return bytes + " B"; 71 | } 72 | int exp = (int) (Math.log(bytes) / Math.log(unit)); 73 | String pre = ("KMGTPE").charAt(exp - 1) + "i"; 74 | return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM maven:3.6.1-amazoncorretto-8 as BUILD 2 | 3 | #ADD m2.tar.gz /root 4 | 5 | COPY . /usr/src/app 6 | RUN mvn -Dmaven.repo.local=/root/m2 --batch-mode -f /usr/src/app/pom.xml clean package 7 | 8 | FROM openjdk:8-jre-slim 9 | EXPOSE 8080 5005 10 | COPY --from=BUILD /usr/src/app/target /opt/target 11 | WORKDIR /opt/target 12 | ENV _JAVA_OPTIONS '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005' 13 | 14 | CMD ["java", "-jar", "app.war"] 15 | 16 | -------------------------------------------------------------------------------- /app/Dockerfile.jre: -------------------------------------------------------------------------------- 1 | FROM debian:9-slim 2 | 3 | COPY target/app.war /root 4 | COPY myjre /root/myjre 5 | 6 | EXPOSE 8080 5005 7 | WORKDIR /root 8 | ENV _JAVA_OPTIONS '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005' 9 | 10 | CMD ["./myjre/bin/java", "-jar", "app.war"] -------------------------------------------------------------------------------- /app/app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: greeting 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: greeting 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: arungupta/skaffold-greeting 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 8080 21 | name: "http" 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: greeting 27 | spec: 28 | selector: 29 | app: greeting 30 | ports: 31 | - name: http 32 | protocol: TCP 33 | port: 80 34 | targetPort: 8080 35 | type: NodePort 36 | -------------------------------------------------------------------------------- /app/greeting-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: greeting 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: greeting 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: arungupta/greeting 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 8080 21 | name: "http" 22 | - containerPort: 5005 23 | name: "debug" 24 | -------------------------------------------------------------------------------- /app/greeting-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: greeting-service 5 | spec: 6 | selector: 7 | app: greeting 8 | ports: 9 | - name: http 10 | protocol: TCP 11 | port: 80 12 | targetPort: 8080 13 | type: LoadBalancer 14 | -------------------------------------------------------------------------------- /app/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.aws.samples.greeting 5 | app 6 | 1.0-SNAPSHOT 7 | war 8 | 9 | 10 | org.springframework.boot 11 | spring-boot-starter-parent 12 | 2.0.5.RELEASE 13 | 14 | 15 | 16 | UTF-8 17 | 1.8 18 | 1.8 19 | arungupta 20 | latest 21 | registry.hub.docker.com 22 | ${docker.registry}/${docker.repo}/${project.build.finalName}:${docker.tag} 23 | localhost 24 | 8080 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | 35 | ${project.artifactId} 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-maven-plugin 40 | 41 | 42 | 43 | 44 | 45 | 46 | jib 47 | 48 | 49 | 50 | com.google.cloud.tools 51 | jib-maven-plugin 52 | 1.1.2 53 | 54 | 55 | openjdk:8-jre-slim 56 | 57 | 58 | ${docker.name} 59 | 60 | 61 | 62 | <_JAVA_OPTIONS>'-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005' 63 | 64 | 65 | 8080 66 | 5005 67 | 68 | 69 | 70 | 71 | 72 | package 73 | 74 | build 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /app/skaffold.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: skaffold/v1alpha2 2 | kind: Config 3 | build: 4 | artifacts: 5 | - imageName: arungupta/skaffold-greeting 6 | deploy: 7 | kubectl: 8 | manifests: 9 | - app.yaml 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/org/aws/samples/greeting/Application.java: -------------------------------------------------------------------------------- 1 | package org.aws.samples.greeting; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/org/aws/samples/greeting/GreetingController.java: -------------------------------------------------------------------------------- 1 | package org.aws.samples.greeting; 2 | 3 | import org.springframework.web.bind.annotation.RestController; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | /** 7 | * @author Arun Gupta 8 | */ 9 | @RestController 10 | public class GreetingController { 11 | 12 | @RequestMapping("/hello") 13 | public String sayHello() { 14 | return "Hello"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /buildspec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 0.2 3 | phases: 4 | install: 5 | commands: 6 | - curl -sS -o aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/1.11.5/2018-12-06/bin/linux/amd64/aws-iam-authenticator 7 | - curl -sS -o kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.11.5/2018-12-06/bin/linux/amd64/kubectl 8 | - chmod +x ./kubectl ./aws-iam-authenticator 9 | - export PATH=$PWD/:$PATH 10 | - apt-get update && apt-get -y install jq python3-pip python3-dev && pip3 install --upgrade awscli 11 | pre_build: 12 | commands: 13 | - TAG="$REPOSITORY_NAME.$REPOSITORY_BRANCH.$ENVIRONMENT_NAME.$(date +%Y-%m-%d.%H.%M.%S).$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | head -c 8)" 14 | - sed -i 's@CONTAINER_IMAGE@'"$REPOSITORY_URI:$TAG"'@' manifests/greeting-pipeline.yaml 15 | - $(aws ecr get-login --no-include-email) 16 | - export KUBECONFIG=$HOME/.kube/config 17 | build: 18 | commands: 19 | - docker image build --tag $REPOSITORY_URI:$TAG app 20 | 21 | post_build: 22 | commands: 23 | - docker image push $REPOSITORY_URI:$TAG 24 | - CREDENTIALS=$(aws sts assume-role --role-arn $EKS_KUBECTL_ROLE_ARN --role-session-name codebuild-kubectl --duration-seconds 900) 25 | - export AWS_ACCESS_KEY_ID="$(echo ${CREDENTIALS} | jq -r '.Credentials.AccessKeyId')" 26 | - export AWS_SECRET_ACCESS_KEY="$(echo ${CREDENTIALS} | jq -r '.Credentials.SecretAccessKey')" 27 | - export AWS_SESSION_TOKEN="$(echo ${CREDENTIALS} | jq -r '.Credentials.SessionToken')" 28 | - export AWS_EXPIRATION=$(echo ${CREDENTIALS} | jq -r '.Credentials.Expiration') 29 | - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME 30 | - kubectl apply -f manifests/greeting-pipeline.yaml 31 | - printf '[{"name":"greeting","imageUri":"%s"}]' $REPOSITORY_URI:$TAG > build.json 32 | artifacts: 33 | files: build.json -------------------------------------------------------------------------------- /images/codepipeline-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/codepipeline-status.png -------------------------------------------------------------------------------- /images/codepipeline-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/codepipeline-template.png -------------------------------------------------------------------------------- /images/docker-debug1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/docker-debug1.png -------------------------------------------------------------------------------- /images/docker-debug2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/docker-debug2.png -------------------------------------------------------------------------------- /images/docker-debug3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/docker-debug3.png -------------------------------------------------------------------------------- /images/istio-dag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/istio-dag.png -------------------------------------------------------------------------------- /images/istio-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/istio-dashboard.png -------------------------------------------------------------------------------- /images/jenkinsx-github-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arun-gupta/kubernetes-for-java-developers/642dfbaabcb9660b295c0a8166919e92f7e7e5fd/images/jenkinsx-github-token.png -------------------------------------------------------------------------------- /images/jenkinsx-log.txt: -------------------------------------------------------------------------------- 1 | Setting the dev namespace to: jx 2 | Namespace jx created 3 | 4 | Using helmBinary helm with feature flag: none 5 | Context "arun@myeks.us-west-2.eksctl.io" modified. 6 | Storing the kubernetes provider eks in the TeamSettings 7 | Enabling helm template mode in the TeamSettings 8 | Git configured for user: Arun Gupta and email arun.gupta@gmail.com 9 | Trying to create ClusterRoleBinding arun-gupta-gmail-com-cluster-admin-binding for role: cluster-admin for user arun.gupta@gmail.com 10 | clusterrolebindings.rbac.authorization.k8s.io "arun-gupta-gmail-com-cluster-admin-binding" not found 11 | Created ClusterRoleBinding arun-gupta-gmail-com-cluster-admin-binding 12 | Using helm2 13 | Skipping tiller 14 | Using helmBinary helm with feature flag: template-mode 15 | Initialising Helm 'init --client-only' 16 | helm installed and configured 17 | Using helm values file: /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/ing-values-292394767 18 | Current configuration dir: /Users/argu/.jx 19 | versionRepository: https://github.com/jenkins-x/jenkins-x-versions.git git ref: 20 | Deleting and cloning the Jenkins X versions repo 21 | Cloning the Jenkins X versions repo https://github.com/jenkins-x/jenkins-x-versions.git with ref refs/heads/master to /Users/argu/.jx/jenkins-x-versions 22 | Enumerating objects: 97, done. 23 | Counting objects: 100% (97/97), done. 24 | Compressing objects: 100% (30/30), done. 25 | Total 1221 (delta 60), reused 93 (delta 60), pack-reused 1124 26 | using stable version 1.3.1 from charts of stable/nginx-ingress from /Users/argu/.jx/jenkins-x-versions 27 | Installing using helm binary: helm 28 | Current configuration dir: /Users/argu/.jx 29 | versionRepository: https://github.com/jenkins-x/jenkins-x-versions.git git ref: 30 | Deleting and cloning the Jenkins X versions repo 31 | Cloning the Jenkins X versions repo https://github.com/jenkins-x/jenkins-x-versions.git with ref refs/heads/master to /Users/argu/.jx/jenkins-x-versions 32 | Enumerating objects: 97, done. 33 | Counting objects: 100% (97/97), done. 34 | Compressing objects: 100% (30/30), done. 35 | Total 1221 (delta 60), reused 93 (delta 60), pack-reused 1124 36 | Fetched chart stable/nginx-ingress to dir /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jxing/chartFiles/nginx-ingress 37 | Generating Chart Template 'template --name jxing --namespace kube-system /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jxing/chartFiles/nginx-ingress --output-dir /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jxing/output --debug --set rbac.create=true --set controller.extraArgs.publish-service=kube-system/jxing-nginx-ingress-controller --values /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/ing-values-292394767' 38 | Applying generated chart stable/nginx-ingress YAML via kubectl in dir: /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jxing/output 39 | clusterrole.rbac.authorization.k8s.io/jxing-nginx-ingress created 40 | clusterrolebinding.rbac.authorization.k8s.io/jxing-nginx-ingress created 41 | configmap/jxing-nginx-ingress-controller created 42 | deployment.extensions/jxing-nginx-ingress-controller created 43 | service/jxing-nginx-ingress-controller created 44 | deployment.extensions/jxing-nginx-ingress-default-backend created 45 | service/jxing-nginx-ingress-default-backend created 46 | role.rbac.authorization.k8s.io/jxing-nginx-ingress created 47 | rolebinding.rbac.authorization.k8s.io/jxing-nginx-ingress created 48 | serviceaccount/jxing-nginx-ingress created 49 | 50 | Removing Kubernetes resources from older releases using selector: jenkins.io/chart-release=jxing,jenkins.io/version!=1.3.1 from all pvc configmap release sa role rolebinding secret 51 | Removing Kubernetes resources from older releases using selector: jenkins.io/chart-release=jxing,jenkins.io/version!=1.3.1,jenkins.io/namespace=kube-system from clusterrole clusterrolebinding 52 | Waiting for external loadbalancer to be created and update the nginx-ingress-controller service in kube-system namespace 53 | External loadbalancer created 54 | Waiting to find the external host name of the ingress controller Service in namespace kube-system with name jxing-nginx-ingress-controller 55 | 56 | On AWS we recommend using a custom DNS name to access services in your Kubernetes cluster to ensure you can use all of your Availability Zones 57 | If you do not have a custom DNS name you can use yet, then you can register a new one here: https://console.aws.amazon.com/route53/home?#DomainRegistration: 58 | 59 | ? Would you like to register a wildcard DNS ALIAS to point at this ELB address? No 60 | 61 | The Ingress address aa5a13f896c4d11e9819c0ab3505777c-c0711574b30062d3.elb.us-west-2.amazonaws.com is not an IP address. We recommend we try resolve it to a public IP address and use that for the domain to access services externally. 62 | ? Would you like wait and resolve this address to an IP address and use it for the domain? Yes 63 | 64 | Waiting for aa5a13f896c4d11e9819c0ab3505777c-c0711574b30062d3.elb.us-west-2.amazonaws.com to be resolvable to an IP address... 65 | aa5a13f896c4d11e9819c0ab3505777c-c0711574b30062d3.elb.us-west-2.amazonaws.com resolved to IP 52.43.206.106 66 | No domain flag provided so using default 52.43.206.106.nip.io to generate Ingress rules 67 | nginx ingress controller installed and configured 68 | Lets set up a Git user name and API token to be able to perform CI/CD 69 | 70 | Select the CI/CD pipelines Git server and user 71 | Setting the pipelines Git server https://github.com and user name arun-gupta. 72 | Saving the Git authentication configuration 73 | Current configuration dir: /Users/argu/.jx 74 | versionRepository: https://github.com/jenkins-x/jenkins-x-versions.git git ref: 75 | Deleting and cloning the Jenkins X versions repo 76 | Cloning the Jenkins X versions repo https://github.com/jenkins-x/jenkins-x-versions.git with ref refs/heads/master to /Users/argu/.jx/jenkins-x-versions 77 | Enumerating objects: 97, done. 78 | Counting objects: 100% (97/97), done. 79 | Compressing objects: 100% (30/30), done. 80 | Total 1221 (delta 60), reused 93 (delta 60), pack-reused 1124 81 | Current configuration dir: /Users/argu/.jx 82 | options.Flags.CloudEnvRepository: https://github.com/jenkins-x/cloud-environments 83 | options.Flags.LocalCloudEnvironment: false 84 | Cloning the Jenkins X cloud environments repo to /Users/argu/.jx/cloud-environments 85 | Current configuration dir: /Users/argu/.jx 86 | options.Flags.CloudEnvRepository: https://github.com/jenkins-x/cloud-environments 87 | options.Flags.LocalCloudEnvironment: false 88 | Cloning the Jenkins X cloud environments repo to /Users/argu/.jx/cloud-environments 89 | Enumerating objects: 1382, done. 90 | Total 1382 (delta 0), reused 0 (delta 0), pack-reused 1382 91 | Setting the dev namespace to: jx 92 | No default password set, generating a random one 93 | Generated helm values /Users/argu/.jx/extraValues.yaml 94 | Creating Secret jx-install-config in namespace jx 95 | Installing Jenkins X platform helm chart from: /Users/argu/.jx/cloud-environments/env-eks 96 | Setting the current namespace to: jx 97 | Installing jx into namespace jx 98 | using stable version 2.0.177 from charts of jenkins-x/jenkins-x-platform from /Users/argu/.jx/jenkins-x-versions 99 | Installing jenkins-x-platform version: 2.0.177 100 | Adding values file /Users/argu/.jx/cloud-environments/env-eks/myvalues.yaml 101 | Adding values file /Users/argu/.jx/adminSecrets.yaml 102 | Adding values file /Users/argu/.jx/extraValues.yaml 103 | Adding values file /Users/argu/.jx/cloud-environments/env-eks/secrets.yaml 104 | Current configuration dir: /Users/argu/.jx 105 | versionRepository: https://github.com/jenkins-x/jenkins-x-versions.git git ref: 106 | Deleting and cloning the Jenkins X versions repo 107 | Cloning the Jenkins X versions repo https://github.com/jenkins-x/jenkins-x-versions.git with ref refs/heads/master to /Users/argu/.jx/jenkins-x-versions 108 | Enumerating objects: 97, done. 109 | Counting objects: 100% (97/97), done. 110 | Compressing objects: 100% (30/30), done. 111 | Total 1221 (delta 60), reused 93 (delta 60), pack-reused 1124 112 | Fetched chart jenkins-x/jenkins-x-platform to dir /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jenkins-x/chartFiles/jenkins-x-platform 113 | Generating Chart Template 'template --name jenkins-x --namespace jx /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jenkins-x/chartFiles/jenkins-x-platform --output-dir /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jenkins-x/output --debug --values /Users/argu/.jx/cloud-environments/env-eks/myvalues.yaml --values /Users/argu/.jx/adminSecrets.yaml --values /Users/argu/.jx/extraValues.yaml --values /Users/argu/.jx/cloud-environments/env-eks/secrets.yaml' 114 | Applying generated chart jenkins-x/jenkins-x-platform YAML via kubectl in dir: /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jenkins-x/output 115 | deployment.extensions/jenkins-x-chartmuseum created 116 | persistentvolumeclaim/jenkins-x-chartmuseum created 117 | secret/jenkins-x-chartmuseum created 118 | service/jenkins-x-chartmuseum created 119 | role.rbac.authorization.k8s.io/cleanup created 120 | rolebinding.rbac.authorization.k8s.io/cleanup created 121 | serviceaccount/cleanup created 122 | clusterrole.rbac.authorization.k8s.io/controllerrole-jx created 123 | clusterrolebinding.rbac.authorization.k8s.io/controllerrole-jx created 124 | deployment.apps/jenkins-x-controllerrole created 125 | role.rbac.authorization.k8s.io/controllerrole created 126 | rolebinding.rbac.authorization.k8s.io/controllerrole created 127 | serviceaccount/jenkins-x-controllerrole created 128 | clusterrole.rbac.authorization.k8s.io/controllerteam-jx created 129 | clusterrolebinding.rbac.authorization.k8s.io/controllerteam-jx created 130 | deployment.apps/jenkins-x-controllerteam created 131 | role.rbac.authorization.k8s.io/controllerteam created 132 | rolebinding.rbac.authorization.k8s.io/controllerteam created 133 | serviceaccount/jenkins-x-controllerteam created 134 | clusterrole.rbac.authorization.k8s.io/controllerworkflow-jx created 135 | clusterrolebinding.rbac.authorization.k8s.io/controllerworkflow-jx created 136 | deployment.apps/jenkins-x-controllerworkflow created 137 | role.rbac.authorization.k8s.io/controllerworkflow created 138 | rolebinding.rbac.authorization.k8s.io/controllerworkflow created 139 | serviceaccount/jenkins-x-controllerworkflow created 140 | configmap/exposecontroller created 141 | role.rbac.authorization.k8s.io/expose created 142 | rolebinding.rbac.authorization.k8s.io/expose created 143 | serviceaccount/expose created 144 | clusterrole.rbac.authorization.k8s.io/gcactivities-jx created 145 | clusterrolebinding.rbac.authorization.k8s.io/gcactivities-jx created 146 | cronjob.batch/jenkins-x-gcactivities created 147 | role.rbac.authorization.k8s.io/gcactivities created 148 | rolebinding.rbac.authorization.k8s.io/gcactivities created 149 | serviceaccount/jenkins-x-gcactivities created 150 | cronjob.batch/jenkins-x-gcpods created 151 | role.rbac.authorization.k8s.io/gcpods created 152 | rolebinding.rbac.authorization.k8s.io/gcpods created 153 | serviceaccount/jenkins-x-gcpods created 154 | clusterrole.rbac.authorization.k8s.io/gcpreviews-jx created 155 | clusterrolebinding.rbac.authorization.k8s.io/gcpreviews-jx created 156 | cronjob.batch/jenkins-x-gcpreviews created 157 | role.rbac.authorization.k8s.io/gcpreviews created 158 | rolebinding.rbac.authorization.k8s.io/gcpreviews created 159 | serviceaccount/jenkins-x-gcpreviews created 160 | deployment.extensions/jenkins-x-heapster created 161 | clusterrolebinding.rbac.authorization.k8s.io/jenkins-x-heapster created 162 | role.rbac.authorization.k8s.io/jenkins-x-heapster-pod-nanny created 163 | rolebinding.rbac.authorization.k8s.io/jenkins-x-heapster-pod-nanny created 164 | service/heapster created 165 | serviceaccount/jenkins-x-heapster created 166 | configmap/jenkins created 167 | persistentvolumeclaim/jenkins created 168 | service/jenkins-agent created 169 | deployment.extensions/jenkins created 170 | service/jenkins created 171 | configmap/jenkins-x-git-kinds created 172 | configmap/jenkins-pod-xml-dlang created 173 | configmap/jenkins-pod-xml-go created 174 | configmap/jenkins-pod-xml-python created 175 | configmap/jenkins-pod-xml-newman created 176 | configmap/jenkins-pod-xml-terraform created 177 | configmap/jenkins-pod-xml-maven created 178 | configmap/jenkins-pod-xml-rust created 179 | configmap/jenkins-pod-xml-python2 created 180 | configmap/jenkins-pod-xml-nodejs created 181 | configmap/jenkins-pod-xml-aws-cdk created 182 | configmap/jenkins-pod-xml-gradle created 183 | configmap/jenkins-pod-xml-maven-java11 created 184 | configmap/jenkins-pod-xml-scala created 185 | configmap/jenkins-pod-xml-python37 created 186 | configmap/jenkins-pod-xml-promote created 187 | configmap/jenkins-pod-xml-maven-nodejs created 188 | configmap/jenkins-pod-xml-swift created 189 | configmap/jenkins-pod-xml-jx-base created 190 | configmap/jenkins-pod-xml-ruby created 191 | clusterrolebinding.rbac.authorization.k8s.io/jenkins-jx-role-binding created 192 | secret/jenkins created 193 | serviceaccount/jenkins created 194 | configmap/jenkins-tests created 195 | deployment.extensions/jenkins-x-mongodb created 196 | persistentvolumeclaim/jenkins-x-mongodb created 197 | secret/jenkins-x-mongodb created 198 | service/jenkins-x-mongodb created 199 | configmap/jenkins-x-monocular-api-config created 200 | deployment.extensions/jenkins-x-monocular-api created 201 | service/jenkins-x-monocular-api created 202 | deployment.extensions/jenkins-x-monocular-prerender created 203 | service/jenkins-x-monocular-prerender created 204 | configmap/jenkins-x-monocular-ui-config created 205 | deployment.extensions/jenkins-x-monocular-ui created 206 | service/jenkins-x-monocular-ui created 207 | configmap/jenkins-x-monocular-ui-vhost created 208 | configmap/nexus created 209 | deployment.extensions/jenkins-x-nexus created 210 | persistentvolumeclaim/jenkins-x-nexus created 211 | secret/nexus created 212 | service/nexus created 213 | role.rbac.authorization.k8s.io/committer created 214 | clusterrolebinding.rbac.authorization.k8s.io/jenkins-x-team-controller created 215 | configmap/jenkins-x-team-controller created 216 | secret/jenkins-docker-cfg created 217 | configmap/jenkins-x-devpod-config created 218 | configmap/jenkins-x-docker-registry created 219 | configmap/jenkins-x-extensions created 220 | secret/jx-basic-auth created 221 | role.rbac.authorization.k8s.io/jx-view created 222 | secret/jenkins-maven-settings created 223 | secret/jenkins-npm-token created 224 | role.rbac.authorization.k8s.io/owner created 225 | configmap/jenkins-x-pod-template-dlang created 226 | configmap/jenkins-x-pod-template-go created 227 | configmap/jenkins-x-pod-template-python created 228 | configmap/jenkins-x-pod-template-newman created 229 | configmap/jenkins-x-pod-template-terraform created 230 | configmap/jenkins-x-pod-template-maven created 231 | configmap/jenkins-x-pod-template-rust created 232 | configmap/jenkins-x-pod-template-python2 created 233 | configmap/jenkins-x-pod-template-nodejs created 234 | configmap/jenkins-x-pod-template-aws-cdk created 235 | configmap/jenkins-x-pod-template-gradle created 236 | configmap/jenkins-x-pod-template-maven-java11 created 237 | configmap/jenkins-x-pod-template-scala created 238 | configmap/jenkins-x-pod-template-python37 created 239 | configmap/jenkins-x-pod-template-promote created 240 | configmap/jenkins-x-pod-template-maven-nodejs created 241 | configmap/jenkins-x-pod-template-swift created 242 | configmap/jenkins-x-pod-template-jx-base created 243 | configmap/jenkins-x-pod-template-ruby created 244 | secret/jenkins-release-gpg created 245 | secret/jenkins-ssh-config created 246 | role.rbac.authorization.k8s.io/viewer created 247 | 248 | Applying Helm hook post-upgrade YAML via kubectl in file: /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jenkins-x/helmHooks/jenkins-x-platform/charts/expose/templates/job.yaml 249 | job.batch/expose created 250 | 251 | Waiting for helm post-upgrade hook Job expose to complete before removing it 252 | Deleting helm hook sources from file: /var/folders/cv/yxmfk09x0ln_pp53287fk775lgvpjt/T/helm-template-workdir-610764150/jenkins-x/helmHooks/jenkins-x-platform/charts/expose/templates/job.yaml 253 | job.batch "expose" deleted 254 | Removing Kubernetes resources from older releases using selector: jenkins.io/chart-release=jenkins-x,jenkins.io/version!=2.0.177 from all pvc configmap release sa role rolebinding secret 255 | Removing Kubernetes resources from older releases using selector: jenkins.io/chart-release=jenkins-x,jenkins.io/version!=2.0.177,jenkins.io/namespace=jx from clusterrole clusterrolebinding 256 | WARNING: waiting for install to be ready, if this is the first time then it will take a while to download images 257 | Jenkins X deployments ready in namespace jx 258 | Configuring the TeamSettings for ImportMode Jenkinsfile 259 | 260 | 261 | ******************************************************** 262 | 263 | NOTE: Your admin password is: 1lw5tgW7dyyePr,bMw_8 264 | 265 | ******************************************************** 266 | 267 | 268 | Configure Jenkins API Token 269 | waiting up to 0s for the Jenkins server to be healty at URL http://jenkins.jx.52.43.206.106.nip.io/login 270 | Generating the API token... 271 | Logged in admin to Jenkins server at http://jenkins.jx.52.43.206.106.nip.io via legacy security realm 272 | Enable CSRF protection at: http://jenkins.jx.52.43.206.106.nip.io/configureSecurity/ 273 | Created user admin API Token for Jenkins server jenkins.jx.52.43.206.106.nip.io at http://jenkins.jx.52.43.206.106.nip.io 274 | Updating Jenkins with new external URL details http://jenkins.jx.52.43.206.106.nip.io 275 | Creating default staging and production environments 276 | Using arun-gupta environment git owner in batch mode. 277 | Using Git provider GitHub at https://github.com 278 | 279 | 280 | About to create repository environment-hawkstar-staging on server https://github.com with user arun-gupta 281 | 282 | 283 | Creating repository arun-gupta/environment-hawkstar-staging 284 | Creating Git repository arun-gupta/environment-hawkstar-staging 285 | Pushed Git repository to https://github.com/arun-gupta/environment-hawkstar-staging 286 | 287 | Creating staging Environment in namespace jx 288 | Created environment staging 289 | Namespace jx-staging created 290 | 291 | Created Jenkins Project: http://jenkins.jx.52.43.206.106.nip.io/job/arun-gupta/job/environment-hawkstar-staging/ 292 | 293 | Note that your first pipeline may take a few minutes to start while the necessary images get downloaded! 294 | 295 | 296 | Creating GitHub webhook for arun-gupta/environment-hawkstar-staging for url http://jenkins.jx.52.43.206.106.nip.io/github-webhook/ 297 | Using Git provider GitHub at https://github.com 298 | 299 | 300 | About to create repository environment-hawkstar-production on server https://github.com with user arun-gupta 301 | 302 | 303 | Creating repository arun-gupta/environment-hawkstar-production 304 | Creating Git repository arun-gupta/environment-hawkstar-production 305 | Pushed Git repository to https://github.com/arun-gupta/environment-hawkstar-production 306 | 307 | Creating production Environment in namespace jx 308 | Created environment production 309 | Namespace jx-production created 310 | 311 | Created Jenkins Project: http://jenkins.jx.52.43.206.106.nip.io/job/arun-gupta/job/environment-hawkstar-production/ 312 | 313 | Note that your first pipeline may take a few minutes to start while the necessary images get downloaded! 314 | 315 | 316 | Creating GitHub webhook for arun-gupta/environment-hawkstar-production for url http://jenkins.jx.52.43.206.106.nip.io/github-webhook/ 317 | 318 | Jenkins X installation completed successfully 319 | 320 | 321 | ******************************************************** 322 | 323 | NOTE: Your admin password is: PASSWORD 324 | 325 | ******************************************************** 326 | 327 | 328 | 329 | Your Kubernetes context is now set to the namespace: jx 330 | To switch back to your original namespace use: jx namespace default 331 | Or to use this context/namespace in just one terminal use: jx shell 332 | For help on switching contexts see: https://jenkins-x.io/developing/kube-context/ 333 | 334 | To import existing projects into Jenkins: jx import 335 | To create a new Spring Boot microservice: jx create spring -d web -d actuator 336 | To create a new microservice from a quickstart: jx create quickstart -------------------------------------------------------------------------------- /manifests/app-hello-howdy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: greeting-hello 5 | labels: 6 | name: greeting 7 | spec: 8 | replicas: 9 | template: 10 | metadata: 11 | labels: 12 | app: greeting 13 | greeting: hello 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: arungupta/greeting:hello 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 8080 21 | name: "http" 22 | --- 23 | apiVersion: extensions/v1beta1 24 | kind: Deployment 25 | metadata: 26 | name: greeting-howdy 27 | labels: 28 | name: greeting 29 | spec: 30 | replicas: 31 | template: 32 | metadata: 33 | labels: 34 | app: greeting 35 | greeting: howdy 36 | spec: 37 | containers: 38 | - name: greeting 39 | image: arungupta/greeting:howdy 40 | imagePullPolicy: IfNotPresent 41 | ports: 42 | - containerPort: 8080 43 | name: "http" 44 | --- 45 | apiVersion: v1 46 | kind: Service 47 | metadata: 48 | name: greeting 49 | spec: 50 | selector: 51 | app: greeting 52 | ports: 53 | - name: http 54 | protocol: TCP 55 | port: 80 56 | targetPort: 8080 57 | type: LoadBalancer 58 | -------------------------------------------------------------------------------- /manifests/app-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: greeting 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: greeting 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: arungupta/greeting 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 8080 21 | name: "http" 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: greeting 27 | spec: 28 | selector: 29 | app: greeting 30 | ports: 31 | - name: http 32 | protocol: TCP 33 | port: 8080 34 | targetPort: 8080 35 | -------------------------------------------------------------------------------- /manifests/app.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: greeting 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: greeting 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: arungupta/greeting 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 8080 21 | name: "http" 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: greeting 27 | spec: 28 | selector: 29 | app: greeting 30 | ports: 31 | - name: http 32 | protocol: TCP 33 | port: 80 34 | targetPort: 8080 35 | type: LoadBalancer 36 | -------------------------------------------------------------------------------- /manifests/appmesh/app-hello-howdy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: talker 5 | namespace: prod 6 | labels: 7 | name: talker 8 | spec: 9 | replicas: 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | greeting: talker 15 | spec: 16 | containers: 17 | - name: greeting 18 | image: arungupta/greeting:hello 19 | ports: 20 | - containerPort: 8080 21 | name: "http" 22 | --- 23 | apiVersion: extensions/v1beta1 24 | kind: Deployment 25 | metadata: 26 | name: hello 27 | namespace: prod 28 | labels: 29 | name: greeting 30 | spec: 31 | replicas: 32 | template: 33 | metadata: 34 | labels: 35 | app: greeting 36 | greeting: hello 37 | spec: 38 | containers: 39 | - name: greeting 40 | image: arungupta/greeting:hello 41 | ports: 42 | - containerPort: 8080 43 | name: "http" 44 | --- 45 | apiVersion: extensions/v1beta1 46 | kind: Deployment 47 | metadata: 48 | name: howdy 49 | namespace: prod 50 | labels: 51 | name: greeting 52 | spec: 53 | replicas: 54 | template: 55 | metadata: 56 | labels: 57 | app: greeting 58 | greeting: howdy 59 | spec: 60 | containers: 61 | - name: greeting 62 | image: arungupta/greeting:howdy 63 | ports: 64 | - containerPort: 8080 65 | name: "http" 66 | -------------------------------------------------------------------------------- /manifests/appmesh/mesh.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: appmesh.k8s.aws/v1beta1 2 | kind: Mesh 3 | metadata: 4 | name: greeting-app 5 | namespace: prod 6 | spec: 7 | cloudMapNamespaceName: greeting-app 8 | serviceDiscoveryType: dns -------------------------------------------------------------------------------- /manifests/appmesh/services.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: mostly-hello 5 | namespace: prod 6 | labels: 7 | app: hello 8 | spec: 9 | ports: 10 | - port: 8080 11 | name: http 12 | --- 13 | apiVersion: v1 14 | kind: Service 15 | metadata: 16 | name: mostly-howdy 17 | namespace: prod 18 | labels: 19 | app: howdy 20 | spec: 21 | ports: 22 | - port: 8080 23 | name: http 24 | --- 25 | apiVersion: v1 26 | kind: Service 27 | metadata: 28 | name: howdy 29 | namespace: prod 30 | labels: 31 | app: greeting 32 | spec: 33 | ports: 34 | - port: 8080 35 | name: http 36 | selector: 37 | greeting: howdy 38 | --- 39 | apiVersion: v1 40 | kind: Service 41 | metadata: 42 | name: hello 43 | namespace: prod 44 | labels: 45 | app: greeting 46 | spec: 47 | ports: 48 | - port: 8080 49 | name: http 50 | selector: 51 | greeting: hello 52 | --- 53 | apiVersion: v1 54 | kind: Service 55 | metadata: 56 | name: talker 57 | namespace: prod 58 | labels: 59 | app: greeting 60 | spec: 61 | ports: 62 | - port: 8080 63 | name: http 64 | selector: 65 | greeting: talker 66 | -------------------------------------------------------------------------------- /manifests/appmesh/virtualnodes.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: appmesh.k8s.aws/v1beta1 2 | kind: VirtualNode 3 | metadata: 4 | name: talker 5 | namespace: prod 6 | spec: 7 | meshName: greeting-app 8 | listeners: 9 | - portMapping: 10 | port: 8080 11 | protocol: http 12 | serviceDiscovery: 13 | dns: 14 | hostName: talker.prod.svc.cluster.local 15 | backends: 16 | - virtualService: 17 | virtualServiceName: mostly-hello.prod.svc.cluster.local 18 | - virtualService: 19 | virtualServiceName: mostly-howdy.prod.svc.cluster.local 20 | --- 21 | apiVersion: appmesh.k8s.aws/v1beta1 22 | kind: VirtualNode 23 | metadata: 24 | name: hello 25 | namespace: prod 26 | spec: 27 | meshName: greeting-app 28 | listeners: 29 | - portMapping: 30 | port: 8080 31 | protocol: http 32 | serviceDiscovery: 33 | dns: 34 | hostName: hello.prod.svc.cluster.local 35 | --- 36 | apiVersion: appmesh.k8s.aws/v1beta1 37 | kind: VirtualNode 38 | metadata: 39 | name: howdy 40 | namespace: prod 41 | spec: 42 | meshName: greeting-app 43 | listeners: 44 | - portMapping: 45 | port: 8080 46 | protocol: http 47 | serviceDiscovery: 48 | dns: 49 | hostName: howdy.prod.svc.cluster.local 50 | --- 51 | apiVersion: appmesh.k8s.aws/v1beta1 52 | kind: VirtualNode 53 | metadata: 54 | name: mostly-howdy 55 | namespace: prod 56 | spec: 57 | meshName: greeting-app 58 | listeners: 59 | - portMapping: 60 | port: 8080 61 | protocol: http 62 | serviceDiscovery: 63 | dns: 64 | hostName: mostly-howdy.prod.svc.cluster.local 65 | --- 66 | apiVersion: appmesh.k8s.aws/v1beta1 67 | kind: VirtualNode 68 | metadata: 69 | name: mostly-hello 70 | namespace: prod 71 | spec: 72 | meshName: greeting-app 73 | listeners: 74 | - portMapping: 75 | port: 8080 76 | protocol: http 77 | serviceDiscovery: 78 | dns: 79 | hostName: mostly-hello.prod.svc.cluster.local 80 | 81 | -------------------------------------------------------------------------------- /manifests/appmesh/virtualservice.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: appmesh.k8s.aws/v1beta1 2 | kind: VirtualService 3 | metadata: 4 | name: mostly-hello.prod.svc.cluster.local 5 | namespace: prod 6 | spec: 7 | meshName: greeting-app 8 | virtualRouter: 9 | name: hello-router 10 | routes: 11 | - name: hello-route 12 | http: 13 | match: 14 | prefix: /hello 15 | action: 16 | weightedTargets: 17 | - virtualNodeName: hello 18 | weight: 90 19 | - virtualNodeName: howdy 20 | weight: 10 21 | --- 22 | apiVersion: appmesh.k8s.aws/v1beta1 23 | kind: VirtualService 24 | metadata: 25 | name: mostly-howdy.prod.svc.cluster.local 26 | namespace: prod 27 | spec: 28 | meshName: greeting-app 29 | virtualRouter: 30 | name: howdy-router 31 | routes: 32 | - name: howdy-route 33 | http: 34 | match: 35 | prefix: /hello 36 | action: 37 | weightedTargets: 38 | - virtualNodeName: howdy 39 | weight: 90 40 | - virtualNodeName: hello 41 | weight: 10 42 | -------------------------------------------------------------------------------- /manifests/greeting-pipeline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: greeting 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: greeting 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: CONTAINER_IMAGE 18 | imagePullPolicy: IfNotPresent 19 | ports: 20 | - containerPort: 8080 21 | --- 22 | apiVersion: v1 23 | kind: Service 24 | metadata: 25 | name: greeting 26 | spec: 27 | selector: 28 | app: greeting 29 | ports: 30 | - name: http 31 | protocol: TCP 32 | port: 8080 33 | targetPort: 8080 34 | type: LoadBalancer -------------------------------------------------------------------------------- /manifests/istio/app-canary.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: greeting-virtual-service 5 | spec: 6 | hosts: 7 | - greeting 8 | http: 9 | - route: 10 | - destination: 11 | host: greeting 12 | subset: greeting-hello 13 | weight: 90 14 | - destination: 15 | host: greeting 16 | subset: greeting-howdy 17 | weight: 10 18 | --- 19 | apiVersion: networking.istio.io/v1alpha3 20 | kind: DestinationRule 21 | metadata: 22 | name: greeting-destination-rule 23 | spec: 24 | host: greeting 25 | subsets: 26 | - name: greeting-hello 27 | labels: 28 | greeting: hello 29 | - name: greeting-howdy 30 | labels: 31 | greeting: howdy 32 | -------------------------------------------------------------------------------- /manifests/istio/app-rule-75-25.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: greeting-virtual-service 5 | spec: 6 | hosts: 7 | - greeting 8 | http: 9 | - route: 10 | - destination: 11 | host: greeting 12 | subset: greeting-hello 13 | weight: 75 14 | - destination: 15 | host: greeting 16 | subset: greeting-howdy 17 | weight: 25 18 | --- 19 | apiVersion: networking.istio.io/v1alpha3 20 | kind: DestinationRule 21 | metadata: 22 | name: greeting-destination-rule 23 | spec: 24 | host: greeting 25 | subsets: 26 | - name: greeting-hello 27 | labels: 28 | greeting: hello 29 | - name: greeting-howdy 30 | labels: 31 | greeting: howdy 32 | -------------------------------------------------------------------------------- /manifests/istio/greeting-delay.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: Gateway 3 | metadata: 4 | name: greeting 5 | spec: 6 | selector: 7 | istio: ingressgateway 8 | servers: 9 | - port: 10 | number: 80 11 | name: http 12 | protocol: HTTP 13 | hosts: 14 | - greeting.com 15 | --- 16 | apiVersion: networking.istio.io/v1alpha3 17 | kind: VirtualService 18 | metadata: 19 | name: greeting 20 | spec: 21 | hosts: 22 | - greeting.com 23 | gateways: 24 | - greeting 25 | http: 26 | - match: 27 | - uri: 28 | prefix: / 29 | fault: 30 | delay: 31 | percent: 100 32 | fixedDelay: 5s 33 | route: 34 | - destination: 35 | host: greeting.default.svc.cluster.local 36 | port: 37 | number: 8080 38 | -------------------------------------------------------------------------------- /manifests/kubemonkey/app-kube-monkey.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: greeting 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: greeting 10 | template: 11 | metadata: 12 | labels: 13 | app: greeting 14 | kube-monkey/enabled: enabled 15 | kube-monkey/identifier: monkey-victim-pods 16 | kube-monkey/mtbf: 2 17 | kube-monkey/kill-mode: random-max-percent 18 | kube-monkey/kill-value: 40 19 | spec: 20 | containers: 21 | - name: greeting 22 | image: arungupta/greeting 23 | imagePullPolicy: IfNotPresent 24 | ports: 25 | - containerPort: 8080 26 | name: "http" 27 | --- 28 | apiVersion: v1 29 | kind: Service 30 | metadata: 31 | name: greeting 32 | spec: 33 | selector: 34 | app: greeting 35 | ports: 36 | - name: http 37 | protocol: TCP 38 | port: 8080 39 | targetPort: 8080 40 | -------------------------------------------------------------------------------- /manifests/kubemonkey/kube-monkey-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: kube-monkey-config-map 5 | namespace: kube-system 6 | data: 7 | config.toml: | 8 | [kubemonkey] 9 | run_hour = 8 10 | start_hour = 10 11 | end_hour = 16 12 | blacklisted_namespaces = ["kube-system"] 13 | whitelisted_namespaces = [""] -------------------------------------------------------------------------------- /manifests/kubemonkey/kube-monkey-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: kube-monkey 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | template: 9 | metadata: 10 | labels: 11 | app: kube-monkey 12 | spec: 13 | containers: 14 | - name: kube-monkey 15 | command: 16 | - "/kube-monkey" 17 | args: ["-v=5", "-log_dir=/var/log/kube-monkey"] 18 | image: ayushsobti/kube-monkey:v0.2.3 19 | volumeMounts: 20 | - name: config-volume 21 | mountPath: "/etc/kube-monkey" 22 | volumes: 23 | - name: config-volume 24 | configMap: 25 | name: kube-monkey-config-map -------------------------------------------------------------------------------- /manifests/myapp/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /manifests/myapp/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "1.0" 3 | description: | 4 | A Helm chart for a web application using microservices deployed in Kubernetes 5 | name: app 6 | version: 0.1.0 7 | -------------------------------------------------------------------------------- /manifests/myapp/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Get the application URL by running: 2 | $ kubectl get svc/{{ .Release.Name }}-webapp -o wide 3 | -------------------------------------------------------------------------------- /manifests/myapp/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{- define "labels" }} 2 | labels: 3 | generator: helm 4 | date: {{ now | htmlDate }} 5 | release: {{ .Release.Name }} 6 | revision: {{ .Release.Revision | quote }} 7 | chart: {{ .Chart.Name }} 8 | version: {{ .Chart.Version }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /manifests/myapp/templates/greeting-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: {{ .Release.Name }}-greeting 5 | labels: 6 | name: {{ .Release.Name }}-greeting 7 | {{- template "labels" . }} 8 | spec: 9 | replicas: {{ .Values.replicaCount }} 10 | template: 11 | metadata: 12 | labels: 13 | app: {{ .Release.Name }}-greeting 14 | spec: 15 | containers: 16 | - name: greeting 17 | image: {{ .Values.greeting.image }}:{{ .Values.image.tag }} 18 | imagePullPolicy: {{ .Values.image.imagePullPolicy }} 19 | ports: 20 | - containerPort: {{ .Values.service.internalPort }} 21 | name: "http" 22 | - containerPort: {{ .Values.service.internalDebugPort }} 23 | name: "debug" 24 | -------------------------------------------------------------------------------- /manifests/myapp/templates/greeting-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ .Release.Name }}-greeting 5 | labels: 6 | name: {{ .Release.Name }}-greeting 7 | {{- template "labels" . }} 8 | spec: 9 | selector: 10 | app: {{ .Release.Name }}-greeting 11 | ports: 12 | - name: http 13 | protocol: TCP 14 | port: {{ .Values.service.externalPort }} 15 | targetPort: {{ .Values.service.internalPort }} 16 | - name: debug 17 | protocol: TCP 18 | port: {{ .Values.service.externalDebugPort }} 19 | targetPort: {{ .Values.service.internalDebugPort }} 20 | type: LoadBalancer -------------------------------------------------------------------------------- /manifests/myapp/values.yaml: -------------------------------------------------------------------------------- 1 | greeting: 2 | image: arungupta/greeting 3 | replicaCount: 1 4 | 5 | image: 6 | tag: latest 7 | pullPolicy: IfNotPresent 8 | 9 | service: 10 | type: LoadBalancer 11 | externalPort: 80 12 | internalPort: 8080 13 | externalDebugPort: 5005 14 | internalDebugPort: 5005 -------------------------------------------------------------------------------- /readme.adoc: -------------------------------------------------------------------------------- 1 | = A Day in Java Developer's Life, with a taste of Kubernetes 2 | :toc: 3 | 4 | Deploying your Java application in a Kubernetes cluster could feel like Alice in Wonderland. You keep going down the rabbit hole and don't know how to make that ride comfortable. This repository explains how a Java application can be deployed, tested, debugged and monitored in Kubernetes. In addition, it also talks about canary deployment and deployment pipeline. 5 | 6 | A comprehensive hands-on course explaining these concepts is available at https://www.linkedin.com/learning/kubernetes-for-java-developers. 7 | 8 | == Application 9 | 10 | We will use a simple Java application built using Spring Boot. The application publishes a REST endpoint that can be invoked at `http://{host}:{port}/hello`. 11 | 12 | The source code is in the `app` directory. 13 | 14 | == Build and Test using Maven 15 | 16 | . Run application: 17 | 18 | cd app 19 | mvn spring-boot:run 20 | 21 | . Test application 22 | 23 | curl http://localhost:8080/hello 24 | 25 | == Build and Test using Docker 26 | 27 | === Build Docker Image using multi-stage Dockerfile 28 | 29 | . Create `m2.tar.gz`: 30 | 31 | mvn -Dmaven.repo.local=./m2 clean package 32 | tar cvf m2.tar.gz ./m2 33 | 34 | . Create Docker image: 35 | 36 | docker image build -t arungupta/greeting . 37 | + 38 | Explain multi-stage Dockerfile. 39 | 40 | === Build Docker Image using https://github.com/GoogleContainerTools/jib[Jib] 41 | 42 | . Create Docker image: 43 | 44 | mvn compile jib:build -Pjib 45 | 46 | The benefits of using Jib over a multi-stage Dockerfile build include: 47 | 48 | * Don't need to install Docker or run a Docker daemon 49 | * Don't need to write a Dockerfile or build the archive of m2 dependencies 50 | * Much faster 51 | * Builds reproducibly 52 | 53 | The above builds directly to your Docker registry. Alternatively, Jib can also build to a Docker daemon: 54 | 55 | mvn compile jib:dockerBuild -Pjib -Ddocker.name=arungupta/greeting 56 | 57 | === Test built container using Docker 58 | 59 | . Run container: 60 | 61 | docker container run --name greeting -p 8080:8080 -d arungupta/greeting 62 | 63 | . Access application: 64 | 65 | curl http://localhost:8080/hello 66 | 67 | . Remove container: 68 | 69 | docker container rm -f greeting 70 | 71 | == Memory Limits for Java Applications 72 | 73 | We will use a simple Java application to show how memory limits can be specified for Java applications. The application allocates one to three 1GB `byte` array based upon the `gigabytes` CLI parameter. By default, only one array is populated. 74 | 75 | The source code is in the `app-memory` directory. 76 | 77 | . Run the Java application using the default settings: 78 | 79 | cd app-memory 80 | mvn clean package exec:exec 81 | + 82 | It shows the output on a MacOS machine as: 83 | + 84 | ``` 85 | ** PROCESSOR AND MEMORY STATS ** 86 | processors: 8 87 | max memory: 3.6 GiB 88 | free memory: 196.7 MiB 89 | total memory: 254.0 MiB 90 | ** PROCESSOR AND MEMORY STATS ** 91 | ==> Array1 initialized 92 | ** PROCESSOR AND MEMORY STATS ** 93 | processors: 8 94 | max memory: 3.6 GiB 95 | free memory: 197.2 MiB 96 | total memory: 1.2 GiB 97 | ** PROCESSOR AND MEMORY STATS ** 98 | ==> Array nullified 99 | ==> GC done 100 | ** PROCESSOR AND MEMORY STATS ** 101 | processors: 8 102 | max memory: 3.6 GiB 103 | free memory: 1.3 GiB 104 | total memory: 1.3 GiB 105 | ** PROCESSOR AND MEMORY STATS ** 106 | ``` 107 | + 108 | `Max memory` is the maximum memory available to JVM. By default, JVM will take up to https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gc-ergonomics.html[25% of the available memory] for heap. This value may not be exactly 25% because part of this memory is used by the JVM. This is also the default or specified value of `-Xmx`. 109 | + 110 | Total memory is the amount of memory used by JVM at that time. This is also the default or specified value of `-Xms`. 111 | + 112 | Free memory is the difference between the total and objects that are being used by the class. 113 | + 114 | Following CLI options are recognized for this `mvn` command: 115 | + 116 | - `gigabytes` with a value of `1`, `2` or `3` 117 | - `xms` with a value such as `1024` 118 | - `xmx` with a value such as `2048` 119 | + 120 | A typical invocation may look like: 121 | + 122 | ``` 123 | mvn exec:exec -Dgigabytes=2 -Dxms=1024 -Dxmx=2048 124 | ``` 125 | 126 | == Minimal Docker Image using Custom JRE 127 | 128 | . Download http://download.oracle.com/otn-pub/java/jdk/11.0.1+13/90cf5d8f270a4347a95050320eef3fb7/jdk-11.0.1_linux-x64_bin.rpm[JDK 11] and `scp` to an https://aws.amazon.com/marketplace/pp/B00635Y2IW/ref=mkt_ste_ec2_lw_os_win[Amazon Linux] instance 129 | . Install JDK 11: 130 | 131 | sudo yum install jdk-11.0.1_linux-x64_bin.rpm 132 | 133 | . Create a custom JRE for the Spring Boot application: 134 | 135 | cp target/app.war target/app.jar 136 | jlink \ 137 | --output myjre \ 138 | --add-modules $(jdeps --print-module-deps target/app.jar),\ 139 | java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,\ 140 | java.management,java.security.jgss,java.instrument 141 | 142 | . Build Docker image using this custom JRE: 143 | 144 | docker image build --file Dockerfile.jre -t arungupta/greeting:jre-slim . 145 | 146 | . List the Docker images and show the difference in sizes: 147 | 148 | [ec2-user@ip-172-31-21-7 app]$ docker image ls | grep greeting 149 | arungupta/greeting jre-slim 9eed25582f36 6 seconds ago 162MB 150 | arungupta/greeting latest 1b7c061dad60 10 hours ago 490MB 151 | 152 | . Run the container: 153 | 154 | docker container run -d -p 8080:8080 arungupta/greeting:jre-slim 155 | 156 | . Access the application: 157 | 158 | curl http://localhost:8080/hello 159 | 160 | == Build and Test using Kubernetes 161 | 162 | There are multiple options to run a single-node k8s cluster on your development machine: 163 | 164 | - https://kubernetes.io/docs/setup/learning-environment/minikube/[minikube] 165 | - https://microk8s.io/[microk8s] 166 | - https://docs.docker.com/docker-for-mac/kubernetes/[Docker Desktop] 167 | - KIND[https://github.com/kubernetes-sigs/kind] 168 | - https://kubernetic.com/[Kubernetic] 169 | 170 | Each of these tools have their own limitations. Often times, customers will create a __dev__ cluster in the cloud as it closely mirrors the __prod__ cluster. This also reduces impedance mismatch between __dev__ and __prod__. 171 | 172 | We will use Docker Desktop on Mac. 173 | 174 | Kubernetes can be easily enabled on a development machine using Docker for Mac as explained at https://docs.docker.com/docker-for-mac/#kubernetes. 175 | 176 | . Ensure that Kubernetes is enabled in Docker for Mac 177 | . Show the list of contexts: 178 | 179 | kubectl config get-contexts 180 | 181 | . Configure kubectl CLI for Kubernetes cluster 182 | 183 | kubectl config use-context docker-for-desktop 184 | 185 | . Install the Helm CLI: 186 | + 187 | brew install kubernetes-helm 188 | + 189 | If Helm CLI is already installed then use `brew upgrade kubernetes-helm`. 190 | + 191 | . Check Helm version: 192 | 193 | helm version 194 | 195 | . Install Helm in Kubernetes cluster: 196 | + 197 | helm init 198 | + 199 | If Helm has already been initialized on the cluster, then you may have to upgrade Tiller: 200 | + 201 | helm init --upgrade 202 | + 203 | . Install the Helm chart: 204 | 205 | cd .. 206 | helm install --name myapp manifests/myapp 207 | 208 | . Check that the pod is running: 209 | 210 | kubectl get pods 211 | 212 | . Check that the service is up: 213 | 214 | kubectl get svc 215 | 216 | . Access the application: 217 | 218 | curl http://$(kubectl get svc/myapp-greeting \ 219 | -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'):8080/hello 220 | 221 | == Debug Docker and Kubernetes using IntelliJ 222 | 223 | You can debug a Docker container and a Kubernetes Pod if they're running locally on your machine. 224 | 225 | === Debug using Kubernetes 226 | 227 | This was tested using Docker for Mac/Kubernetes. Use the previously deployed Helm chart. 228 | 229 | . Show service: 230 | + 231 | kubectl get svc 232 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 233 | greeting-service LoadBalancer 10.101.39.100 80:30854/TCP 8m 234 | kubernetes ClusterIP 10.96.0.1 443/TCP 90d 235 | myapp-greeting LoadBalancer 10.108.104.178 localhost 8080:32189/TCP,5005:31117/TCP 4s 236 | + 237 | Highlight the debug port is also forwarded. 238 | + 239 | . In IntelliJ, `Run`, `Debug`, `Remote`: 240 | + 241 | image::images/docker-debug1.png[] 242 | + 243 | . Click on `Debug`, setup a breakpoint in the class: 244 | + 245 | image::images/docker-debug2.png[] 246 | + 247 | . Access the application: 248 | 249 | curl http://$(kubectl get svc/myapp-greeting \ 250 | -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'):8080/hello 251 | 252 | . Show the breakpoint hit in IntelliJ: 253 | + 254 | image::images/docker-debug3.png[] 255 | + 256 | . Delete the Helm chart: 257 | 258 | helm delete --purge myapp 259 | 260 | === Debug using Docker 261 | 262 | This was tested using Docker for Mac. 263 | 264 | . Run container: 265 | 266 | docker container run --name greeting -p 8080:8080 -p 5005:5005 -d arungupta/greeting 267 | 268 | . Check container: 269 | 270 | $ docker container ls -a 271 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 272 | 724313157e3c arungupta/greeting "java -jar app-swarm…" 3 seconds ago Up 2 seconds 0.0.0.0:5005->5005/tcp, 0.0.0.0:8080->8080/tcp greeting 273 | 274 | . Setup breakpoint as explained above. 275 | . Access the application using `curl http://localhost:8080/resources/greeting`. 276 | 277 | == Kubernetes Cluster on AWS 278 | 279 | This application will be deployed to an https://aws.amazon.com/eks/[Amazon EKS] cluster. If you're looking for a self-paced workshop that provide detailed instructions to get you started with EKS then https://eksworkshop.com[eksworkshop.com] is your place. 280 | 281 | Let's create the cluster first. 282 | 283 | . Install http://eksctl.io/[eksctl] CLI: 284 | 285 | brew install weaveworks/tap/eksctl 286 | 287 | . Create EKS cluster: 288 | 289 | eksctl create cluster --name myeks --nodes 4 --region us-west-2 290 | 2018-10-25T13:45:38+02:00 [ℹ] setting availability zones to [us-west-2a us-west-2c us-west-2b] 291 | 2018-10-25T13:45:39+02:00 [ℹ] using "ami-0a54c984b9f908c81" for nodes 292 | 2018-10-25T13:45:39+02:00 [ℹ] creating EKS cluster "myeks" in "us-west-2" region 293 | 2018-10-25T13:45:39+02:00 [ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial nodegroup 294 | 2018-10-25T13:45:39+02:00 [ℹ] if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-west-2 --name=myeks' 295 | 2018-10-25T13:45:39+02:00 [ℹ] creating cluster stack "eksctl-myeks-cluster" 296 | 2018-10-25T13:57:33+02:00 [ℹ] creating nodegroup stack "eksctl-myeks-nodegroup-0" 297 | 2018-10-25T14:01:18+02:00 [✔] all EKS cluster resource for "myeks" had been created 298 | 2018-10-25T14:01:18+02:00 [✔] saved kubeconfig as "/Users/argu/.kube/config" 299 | 2018-10-25T14:01:19+02:00 [ℹ] the cluster has 0 nodes 300 | 2018-10-25T14:01:19+02:00 [ℹ] waiting for at least 4 nodes to become ready 301 | 2018-10-25T14:01:50+02:00 [ℹ] the cluster has 4 nodes 302 | 2018-10-25T14:01:50+02:00 [ℹ] node "ip-192-168-161-180.us-west-2.compute.internal" is ready 303 | 2018-10-25T14:01:50+02:00 [ℹ] node "ip-192-168-214-48.us-west-2.compute.internal" is ready 304 | 2018-10-25T14:01:50+02:00 [ℹ] node "ip-192-168-75-44.us-west-2.compute.internal" is ready 305 | 2018-10-25T14:01:50+02:00 [ℹ] node "ip-192-168-82-236.us-west-2.compute.internal" is ready 306 | 2018-10-25T14:01:52+02:00 [ℹ] kubectl command should work with "/Users/argu/.kube/config", try 'kubectl get nodes' 307 | 2018-10-25T14:01:52+02:00 [✔] EKS cluster "myeks" in "us-west-2" region is ready 308 | 309 | . Check the nodes: 310 | 311 | kubectl get nodes 312 | NAME STATUS ROLES AGE VERSION 313 | ip-192-168-161-180.us-west-2.compute.internal Ready 52s v1.10.3 314 | ip-192-168-214-48.us-west-2.compute.internal Ready 57s v1.10.3 315 | ip-192-168-75-44.us-west-2.compute.internal Ready 57s v1.10.3 316 | ip-192-168-82-236.us-west-2.compute.internal Ready 54s v1.10.3 317 | 318 | . Get the list of configs: 319 | + 320 | kubectl config get-contexts 321 | CURRENT NAME CLUSTER AUTHINFO NAMESPACE 322 | * arun@myeks.us-west-2.eksctl.io myeks.us-west-2.eksctl.io arun@myeks.us-west-2.eksctl.io 323 | docker-for-desktop docker-for-desktop-cluster docker-for-desktop 324 | + 325 | As indicated by `*`, kubectl CLI configuration is updated to the recently created cluster. 326 | 327 | == Migrate from Dev to Prod 328 | 329 | . Explicitly set the context: 330 | 331 | kubectl config use-context arun@myeks.us-west-2.eksctl.io 332 | 333 | . Install Helm: 334 | 335 | kubectl -n kube-system create sa tiller 336 | kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller 337 | helm init --service-account tiller 338 | 339 | . Check the list of pods: 340 | 341 | kubectl get pods -n kube-system 342 | NAME READY STATUS RESTARTS AGE 343 | aws-node-774jf 1/1 Running 1 2m 344 | aws-node-jrf5r 1/1 Running 0 2m 345 | aws-node-n46tw 1/1 Running 0 2m 346 | aws-node-slgns 1/1 Running 0 2m 347 | kube-dns-7cc87d595-5tskv 3/3 Running 0 8m 348 | kube-proxy-2ghg6 1/1 Running 0 2m 349 | kube-proxy-hqxwg 1/1 Running 0 2m 350 | kube-proxy-lrwrr 1/1 Running 0 2m 351 | kube-proxy-x77tq 1/1 Running 0 2m 352 | tiller-deploy-895d57dd9-txqk4 1/1 Running 0 15s 353 | 354 | . Redeploy the application: 355 | 356 | helm install --name myapp manifests/myapp 357 | 358 | . Get the service: 359 | + 360 | kubectl get svc 361 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 362 | kubernetes ClusterIP 10.100.0.1 443/TCP 17m 363 | myapp-greeting LoadBalancer 10.100.241.250 a8713338abef211e8970816cb629d414-71232674.us-east-1.elb.amazonaws.com 8080:32626/TCP,5005:30739/TCP 2m 364 | + 365 | It shows the port `8080` and `5005` are published and an Elastic Load Balancer is provisioned. It takes about three minutes for the load balancer to be ready. 366 | + 367 | . Access the application: 368 | 369 | curl http://$(kubectl get svc/myapp-greeting \ 370 | -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'):8080/hello 371 | 372 | . Delete the application: 373 | 374 | helm delete --purge myapp 375 | 376 | == Service Mesh using AWS App Mesh 377 | 378 | https://https://aws.amazon.com/app-mesh/[AWS App Mesh] is a service mesh that provides application-level networking to make it easy for your services to communicate with each other across multiple types of compute infrastructure. App Mesh can be used with Amazon EKS or Kubernetes running on AWS. In addition, it also works with other container services offered by AWS such as AWS Fargate and Amazon ECS. It also works with microservices deployed on Amazon EC2. 379 | 380 | A thorough detailed example that shows how to use App Mesh with EKS is available at https://eksworkshop.com/servicemesh_with_appmesh/[Service Mesh with App Mesh]. This section provides a simplistic setup using the configuration files from there. 381 | 382 | All scripts used in this section are in the `manifests/appmesh` directory. 383 | 384 | === Setup IAM Permissions 385 | 386 | . Set a variable `ROLE_NAME` to IAM role for the EKS worker nodes: 387 | 388 | ROLE_NAME=$(aws iam list-roles \ 389 | --query \ 390 | 'Roles[?contains(RoleName,`eksctl-myeks-nodegroup`)].RoleName' --output text) 391 | 392 | . Setup permissions for the worker nodes: 393 | 394 | aws iam attach-role-policy \ 395 | --role-name $ROLE_NAME \ 396 | --policy-arn arn:aws:iam::aws:policy/AWSAppMeshFullAccess 397 | 398 | === Configure App Mesh 399 | 400 | . Enable side-car injection by running `create.sh` script from https://github.com/aws/aws-app-mesh-examples/tree/master/examples/apps/djapp/2_create_injector. You need to change `ca-bundle.sh` and change `MESH_NAME` to `greeting-app`. 401 | . Create `prod` namespace: 402 | 403 | kubectl create namespace prod 404 | 405 | . Label prod namespace: 406 | 407 | kubectl label namespace prod appmesh.k8s.aws/sidecarInjectorWebhook=enabled 408 | 409 | . Create CRDs: 410 | 411 | kubectl create -f https://raw.githubusercontent.com/aws/aws-app-mesh-examples/master/examples/apps/djapp/3_add_crds/mesh-definition.yaml 412 | kubectl create -f https://raw.githubusercontent.com/aws/aws-app-mesh-examples/master/examples/apps/djapp/3_add_crds/virtual-node-definition.yaml 413 | kubectl create -f https://raw.githubusercontent.com/aws/aws-app-mesh-examples/master/examples/apps/djapp/3_add_crds/virtual-service-definition.yaml 414 | kubectl create -f https://raw.githubusercontent.com/aws/aws-app-mesh-examples/master/examples/apps/djapp/3_add_crds/controller-deployment.yaml 415 | 416 | === Create App Mesh Components 417 | 418 | . Create a Mesh: 419 | 420 | kubectl create -f mesh.yaml 421 | 422 | . Create Virtual Nodes: 423 | 424 | kubectl create -f virtualnodes.yaml 425 | 426 | . Create a Virtual Services: 427 | 428 | kubectl create -f virtualservice.yaml 429 | 430 | . Create deployments: 431 | 432 | kubectl create -f app-hello-howdy.yaml 433 | 434 | . Create services: 435 | 436 | kubectl create -f services.yaml 437 | 438 | === Traffic Shifting 439 | 440 | . Find the name of the talker pod: 441 | 442 | TALKER_POD=$(kubectl get pods \ 443 | -nprod -lgreeting=talker \ 444 | -o jsonpath='{.items[0].metadata.name}') 445 | 446 | . Exec into the talker pod: 447 | 448 | kubectl exec -nprod $TALKER_POD -it bash 449 | 450 | . Invoke the mostly-hello service to get back mostly `Hello` response: 451 | 452 | while [ 1 ]; do curl http://mostly-hello.prod.svc.cluster.local:8080/hello; echo;done 453 | 454 | . `CTRL`+`C` to break the loop. 455 | 456 | . Invoke the mostly-howdy service to get back mostly `Howdy` response: 457 | 458 | while [ 1 ]; do curl http://mostly-howdy.prod.svc.cluster.local:8080/hello; echo;done 459 | 460 | . `CTRL`+`C` to break the loop. 461 | 462 | == Service Mesh using Istio 463 | 464 | https://istio.io/[Istio] is is a layer 4/7 proxy that routes and load balances traffic over HTTP, WebSocket, HTTP/2, gRPC and supports application protocols such as MongoDB and Redis. Istio uses the Envoy proxy to manage all inbound/outbound traffic in the service mesh. 465 | 466 | Istio has a wide variety of traffic management features that live outside the application code, such as A/B testing, phased/canary rollouts, failure recovery, circuit breaker, layer 7 routing and policy enforcement (all provided by the Envoy proxy). Istio also supports ACLs, rate limits, quotas, authentication, request tracing and telemetry collection using its Mixer component. The goal of the Istio project is to support traffic management and security of microservices without requiring any changes to the application; it does this by injecting a sidecar into your pod that handles all network communications. 467 | 468 | More details at https://aws.amazon.com/blogs/opensource/getting-started-istio-eks/[Getting Started with Istio on Amazon EKS]. 469 | 470 | === Install and Configure 471 | 472 | . Download Istio: 473 | 474 | curl -L https://git.io/getLatestIstio | sh - 475 | cd istio-1.* 476 | 477 | . Include `istio-1.*/bin` directory in `PATH` 478 | . Install Istio on Amazon EKS: 479 | 480 | helm install \ 481 | --wait \ 482 | --name istio \ 483 | --namespace istio-system \ 484 | install/kubernetes/helm/istio \ 485 | --set tracing.enabled=true \ 486 | --set grafana.enabled=true 487 | 488 | . Verify: 489 | + 490 | kubectl get pods -n istio-system 491 | NAME READY STATUS RESTARTS AGE 492 | grafana-75485f89b9-4lwg5 1/1 Running 0 1m 493 | istio-citadel-84fb7985bf-4dkcx 1/1 Running 0 1m 494 | istio-egressgateway-bd9fb967d-bsrhz 1/1 Running 0 1m 495 | istio-galley-655c4f9ccd-qwk42 1/1 Running 0 1m 496 | istio-ingressgateway-688865c5f7-zj9db 1/1 Running 0 1m 497 | istio-pilot-6cd69dc444-9qstf 2/2 Running 0 1m 498 | istio-policy-6b9f4697d-g8hc6 2/2 Running 0 1m 499 | istio-sidecar-injector-8975849b4-cnd6l 1/1 Running 0 1m 500 | istio-statsd-prom-bridge-7f44bb5ddb-8r2zx 1/1 Running 0 1m 501 | istio-telemetry-6b5579595f-nlst8 2/2 Running 0 1m 502 | istio-tracing-ff94688bb-2w4wg 1/1 Running 0 1m 503 | prometheus-84bd4b9796-t9kk5 1/1 Running 0 1m 504 | + 505 | Check that both Tracing and Grafana add-ons are enabled. 506 | + 507 | . Enable side car injection for all pods in `default` namespace 508 | 509 | kubectl label namespace default istio-injection=enabled 510 | 511 | . From the repo's main directory, deploy the application: 512 | 513 | kubectl apply -f manifests/app.yaml 514 | 515 | . Check pods and note that it has two containers (one for the application and one for the sidecar): 516 | 517 | kubectl get pods -l app=greeting 518 | NAME READY STATUS RESTARTS AGE 519 | greeting-d4f55c7ff-6gz8b 2/2 Running 0 5s 520 | 521 | . Get list of containers in the pod: 522 | 523 | kubectl get pods -l app=greeting -o jsonpath={.items[*].spec.containers[*].name} 524 | greeting istio-proxy 525 | 526 | . Get response: 527 | 528 | curl http://$(kubectl get svc/greeting \ 529 | -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/hello 530 | 531 | === Traffic Shifting 532 | 533 | . Deploy application with two versions of `greeting`, one that returns `Hello` and another that returns `Howdy`: 534 | 535 | kubectl delete -f manifests/app.yaml 536 | kubectl apply -f manifests/app-hello-howdy.yaml 537 | 538 | . Check the list of pods: 539 | 540 | kubectl get pods -l app=greeting 541 | NAME READY STATUS RESTARTS AGE 542 | greeting-hello-69cc7684d-7g4bx 2/2 Running 0 1m 543 | greeting-howdy-788b5d4b44-g7pml 2/2 Running 0 1m 544 | 545 | . Access application multipe times to see different response: 546 | 547 | for i in {1..10} 548 | do 549 | curl -q http://$(kubectl get svc/greeting -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/hello 550 | echo 551 | done 552 | 553 | . Setup an Istio rule to split traffic between 75% to `Hello` and 25% to `Howdy` version of the `greeting` service: 554 | 555 | kubectl apply -f manifests/istio/app-rule-75-25.yaml 556 | 557 | . Invoke the service again to see the traffic split between two services. 558 | 559 | === Canary Deployment 560 | 561 | . Setup an Istio rule to divert 10% traffic to canary: 562 | 563 | kubectl delete -f manifests/istio/app-rule-75-25.yaml 564 | kubectl apply -f manifests/istio/app-canary.yaml 565 | 566 | . Access application multipe times to see ~10% greeting messages with `Howdy`: 567 | 568 | for i in {1..50} 569 | do 570 | curl -q http://$(kubectl get svc/greeting -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/hello 571 | echo 572 | done 573 | 574 | === Distributed Tracing 575 | 576 | Istio is deployed as a sidecar proxy into each of your pods; this means it can see and monitor all the traffic flows between your microservices and generate a graphical representation of your mesh traffic. We’ll use the application you deployed in the previous step to demonstrate this. 577 | 578 | By default, tracing is disabled. `--set tracing.enabled=true` was used during Istio installation to ensure tracing was enabled. 579 | 580 | Setup access to the tracing dashboard URL using port-forwarding: 581 | 582 | kubectl port-forward \ 583 | -n istio-system \ 584 | pod/$(kubectl get pod \ 585 | -n istio-system \ 586 | -l app=jaeger \ 587 | -o jsonpath='{.items[0].metadata.name}') 16686:16686 & 588 | 589 | Access the dashboard at http://localhost:16686, click on `Dependencies`, `DAG`. 590 | 591 | image::images/istio-dag.png[] 592 | 593 | === Metrics using Grafana 594 | 595 | . By default, Grafana is disabled. `--set grafana.enabled=true` was used during Istio installation to ensure Grafana was enabled. Alternatively, the Grafana add-on can be installed as: 596 | 597 | kubectl apply -f install/kubernetes/addons/grafana.yaml 598 | 599 | . Verify: 600 | 601 | kubectl get pods -l app=grafana -n istio-system 602 | NAME READY STATUS RESTARTS AGE 603 | grafana-75485f89b9-n4skw 1/1 Running 0 10m 604 | 605 | . Forward Istio dashboard using Grafana UI: 606 | 607 | kubectl -n istio-system \ 608 | port-forward $(kubectl -n istio-system \ 609 | get pod -l app=grafana \ 610 | -o jsonpath='{.items[0].metadata.name}') 3000:3000 & 611 | 612 | . View Istio dashboard http://localhost:3000. Click on `Home`, `Istio Workload Dashboard`. 613 | 614 | . Invoke the endpoint: 615 | 616 | curl http://$(kubectl get svc/greeting \ 617 | -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/hello 618 | 619 | image::images/istio-dashboard.png[] 620 | 621 | === Timeouts 622 | 623 | Delays and timeouts can be injected in services. 624 | 625 | . Deploy the application: 626 | 627 | kubectl delete -f manifests/app.yaml 628 | kubectl apply -f manifests/app-ingress.yaml 629 | 630 | . Add a 5 seconds delay to calls to the service: 631 | 632 | kubectl apply -f manifests/istio/greeting-delay.yaml 633 | 634 | . Invoke the service using a 2 seconds timeout: 635 | 636 | export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') 637 | export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http")].port}') 638 | export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT 639 | curl --connect-timeout 2 http://$GATEWAY_URL/resources/greeting 640 | 641 | The service will timeout in 2 seconds. 642 | 643 | == Chaos using kube-monkey 644 | 645 | https://github.com/asobti/kube-monkey[kube-monkey] is an implementation of Netflix's Chaos Monkey for Kubernetes clusters. It randomly deletes Kubernetes pods in the cluster encouraging and validating the development of failure-resilient services. 646 | 647 | . Create kube-monkey configuration: 648 | 649 | kubectl apply -f manifests/kubemonkey/kube-monkey-configmap.yaml 650 | 651 | . Run kube-monkey: 652 | 653 | kubectl apply -f manifests/kubemonkey/kube-monkey-deployment.yaml 654 | 655 | . Deploy an app that opts-in for pod deletion: 656 | 657 | kubectl apply -f manifests/kubemonkey/app-kube-monkey.yaml 658 | 659 | This application agrees to kill up to 40% of pods. The schedule of deletion is defined by kube-monkey configuration and is defined to be between 10am and 4pm on weekdays. 660 | 661 | == Deployment Pipeline using Skaffold 662 | 663 | https://github.com/GoogleContainerTools/skaffold[Skaffold] is a command line utility that facilitates continuous development for Kubernetes applications. With Skaffold, you can iterate on your application source code locally then deploy it to a remote Kubernetes cluster. 664 | 665 | . Check context: 666 | 667 | kubectl config get-contexts 668 | CURRENT NAME CLUSTER AUTHINFO NAMESPACE 669 | arun@eks-gpu.us-west-2.eksctl.io eks-gpu.us-west-2.eksctl.io arun@eks-gpu.us-west-2.eksctl.io 670 | * arun@myeks.us-east-1.eksctl.io myeks.us-east-1.eksctl.io arun@myeks.us-east-1.eksctl.io 671 | docker-for-desktop docker-for-desktop-cluster docker-for-desktop 672 | 673 | . Change to use local Kubernetes cluster: 674 | 675 | kubectl config use-context docker-for-desktop 676 | 677 | . Download Skaffold: 678 | 679 | curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-darwin-amd64 \ 680 | && chmod +x skaffold 681 | 682 | . Open http://localhost:8080/resources/greeting in browser. This will show the page is not available. 683 | . Run Skaffold in the application directory: 684 | 685 | cd app 686 | skaffold dev 687 | 688 | . Refresh the page in browser to see the output. 689 | 690 | == Deployment Pipeline using CodePipeline 691 | 692 | Complete detailed instructions are available at https://eksworkshop.com/codepipeline/. 693 | 694 | === Create IAM role 695 | 696 | . Create an IAM role and add an in-line policy that will allow the CodeBuild stage to interact with the EKS cluster: 697 | 698 | ACCOUNT_ID=`aws sts get-caller-identity --query Account --output text` 699 | TRUST="{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \"Principal\": { \"AWS\": \"arn:aws:iam::${ACCOUNT_ID}:root\" }, \"Action\": \"sts:AssumeRole\" } ] }" 700 | echo '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "eks:Describe*", "Resource": "*" } ] }' > /tmp/iam-role-policy 701 | aws iam create-role --role-name EksWorkshopCodeBuildKubectlRole --assume-role-policy-document "$TRUST" --output text --query 'Role.Arn' 702 | aws iam put-role-policy --role-name EksWorkshopCodeBuildKubectlRole --policy-name eks-describe --policy-document file:///tmp/iam-role-policy 703 | 704 | . Add this IAM role to aws-auth ConfigMap for the EKS cluster: 705 | 706 | ROLE=" - rolearn: arn:aws:iam::$ACCOUNT_ID:role/EksWorkshopCodeBuildKubectlRole\n username: build\n groups:\n - system:masters" 707 | kubectl get -n kube-system configmap/aws-auth -o yaml | awk "/mapRoles: \|/{print;print \"$ROLE\";next}1" > /tmp/aws-auth-patch.yml 708 | kubectl patch configmap/aws-auth -n kube-system --patch "$(cat /tmp/aws-auth-patch.yml)" 709 | 710 | === Create CloudFormation template 711 | 712 | . Fork the repo https://github.com/aws-samples/kubernetes-for-java-developers 713 | . Create a new GitHub token https://github.com/settings/tokens/new, select `repo` as the scope, click on `Generate Token` to generate the token. Copy the generated token. 714 | . Launch https://console.aws.amazon.com/cloudformation/home?#/stacks/create/review?stackName=eksws-codepipeline&templateURL=https://s3.amazonaws.com/eksworkshop.com/templates/master/ci-cd-codepipeline.cfn.yml[CodePipeline CloudFormation template]. 715 | . Specify the correct values for `GitHubUser`, `GitHubToken`, `GitSourceRepo` and `EKS cluster name`. Change the branch if you need to: 716 | + 717 | image::images/codepipeline-template.png[] 718 | + 719 | Click on `Create stack` to create the resources. 720 | 721 | === View CodePipeline 722 | 723 | . Once the stack creation is complete, open https://us-west-2.console.aws.amazon.com/codesuite/codepipeline/pipelines?region=us-west-2#[CodePipeline in the AWS Console]. 724 | . Select the pipeline and wait for the pipeline status to complete: 725 | + 726 | image::images/codepipeline-status.png[] 727 | + 728 | . Access the service: 729 | 730 | curl http://$(kubectl get svc/greeting -n default \ 731 | -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'):8080/hello 732 | 733 | 734 | == Deployment Pipeline using Jenkins X 735 | 736 | . Install `jx` CLI: 737 | 738 | brew tap jenkins-x/jx 739 | brew install jx 740 | 741 | . Create a new https://github.com/settings/tokens[GitHub token] with the following scope: 742 | + 743 | image::images/jenkinsx-github-token.png[] 744 | + 745 | . Install Jenkins X on Amazon EKS: 746 | + 747 | jx install --provider=eks --git-username arun-gupta --git-api-token GITHUB_TOKEN --batch-mode 748 | + 749 | link:images/jenkinsx-log.txt[Log] shows complete run of the command. 750 | + 751 | . Use `jx import` to import a project. Need `Dockerfile` and maven application in the root directory. 752 | 753 | --------------------------------------------------------------------------------