├── .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 |
--------------------------------------------------------------------------------