Jenkins X Hybrid TLS¶
Jenkins X Hybrid TLS is a configuration of Jenkins X using both Static Jenkins and Jenkins X Serverless with Tekton within the same cluster. As the TLS suffix hints at, it also uses TLS for both installations to make sure all the services and your applications are accessible via https with a valid certificate.
Pre-requisites¶
- GCP account
- with active subscription
- with an active project with which you are authenticated
gcloud
CLI- Jenkins X CLI
jx
- httpie or curl
Steps¶
- create JX cluster in GKE with static Jenkins
- without Nexus
- create Go (lang) quickstart
- configure TLS
- install Serverless Jenkins X in the same cluster
- create Spring Boot Quickstart
- configure TLS for Serverless namespaces only
- re-install Jenkins X with Nexus
Static¶
Prepare¶
Variables¶
CLUSTER_NAME=#name of your cluster
PROJECT=#name of your GCP project
REGION=#GCP region to install cluster in
GITHUB_USER=#your GitHub Username
GITHUB_TOKEN=#GitHub apitoken
myvalues.yaml¶
We're going to use a demo application based on Go, so we don't need Nexus.
To configure Jenkins X to skip Nexus' installation, create the file myvalues.yaml
with the following contents:
Install JX¶
Make sure you execute this command where you have the myvalues.yaml
file.
jx create cluster gke \
--cluster-name ${CLUSTER_NAME} \
--project-id ${PROJECT} \
--region ${REGION} \
--machine-type n1-standard-2 \
--min-num-nodes 1 \
--max-num-nodes 2 \
--default-admin-password=admin \
--default-environment-prefix jx-rocks \
--git-provider-kind github \
--git-username ${GITHUB_USER} \
--git-provider-kind github \
--git-api-token ${GITHUB_TOKEN} \
--batch-mode
Go Quickstart¶
jx create quickstart \
-l go --org ${GITHUB_USER} \
--project-name jx-static-go \
--import-mode=Jenkinsfile \
--deploy-kind default \
-b
Watch activity¶
You can either go to Jenkins and watch the job there: jx console
or watch in your console via jx get activity
.
Once the build completes, you should see something like the line below, you can test the application.
Promoted 28m5s 1m41s Succeeded Application is at: http://jx-static-go.jx-staging.34.90.105.15.nip.io
Test application¶
To confirm the application is running in the staging environment:
Which should show something like this:
LB_IP=$(kubectl get svc -n kube-system jxing-nginx-ingress-controller -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
Which should show the following:
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 43
Content-Type: text/plain; charset=utf-8
Date: Thu, 13 Jun 2019 12:17:39 GMT
Server: nginx/1.15.8
Hello from: Jenkins X golang http example
Configure TLS¶
Make sure you have two things:
- the address of your LoadBalancer (see below how to retrieve this)
- a Domain name with a quick and easy DNS configuration (incl. wildcard support)
Retrieve LoadBalancer address¶
LB_IP=$(kubectl get svc -n kube-system jxing-nginx-ingress-controller -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
Configure DNS¶
Go to your Domain provider of choice, if you don't have one, consider Google Domains for 12 Euro per year. They might no be the cheapest, but the service is great and works quick - changes like we're about to do, take a few minutes to be effectuated.
Configure the following wildcards to direct to your LoadBalancer's IP address:
*.jx
- type A*.jx-staging
- type A*.jx-production
- type A*.serverless
- type A (for the serverless section)
Upgrade Ingress¶
To configure TLS inside Jenkins X, we make use of Let's Encrypt and cert-manager.
To get Jenkins X to configure TLS, we use the jx upgrade ingress
command.
Info
To be sure, the Domain name above should the base hostname only. Any resource within your JX installation will automatically get the following domain name: {name}.{namespace}.{DOMAIN}
. For example, if your domain is example.com
Jenkins will become jenkins.jx.example.com
.
Test applications¶
Confirm your application now has a https protocol.
Serverless¶
Prepare¶
The values for INGRESS_NS
and INGRESS_DEP
are the default based on the static install created above. If your ingress controller namespace and/or deployment have different names, replace the values.
For the LB_IP
, we're also assuming default names and namespaces.
PROVIDER=gke
LB_IP=$(kubectl get svc -n kube-system jxing-nginx-ingress-controller -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
DOMAIN_SUFFIX=#your domain name
DOMAIN=serverless.${DOMAIN_SUFFIX}
INGRESS_NS=kube-system
INGRESS_DEP=jxing-nginx-ingress-controller
INSTALL_NS=cdx
PROJECT=#your GCP project
Info
We're going to use the cdx
namespace, this will create namespaces such as cdx
and cdx-staging
. In order to avoid having to register every environment in at our DNS provider, we will use an additional domain prefix serverless
. Making the domain serverless.{DOMAIN}
and the JX components {name}.cdx.serverless.{DOMAIN}
.
Install Serverless JX¶
jx install \
--provider $PROVIDER \
--external-ip $LB_IP \
--domain $DOMAIN \
--default-admin-password=admin \
--ingress-namespace $INGRESS_NS \
--ingress-deployment $INGRESS_DEP \
--default-environment-prefix tekton \
--git-provider-kind github \
--namespace ${INSTALL_NS} \
--prow \
--docker-registry gcr.io \
--docker-registry-org $PROJECT \
--tekton \
--kaniko \
-b
Spring Boot Quickstart¶
Create quickstart¶
Add controller¶
Assuming you kept the group the same, you should find a folder src/main/java/com/example/jxspringbootdemo
containing a file, DemoApplication.java
.
We're going to have to add two files to the same folder:
Greeting.java
GreetingController.java
Greeting¶
package com.example.jxspringbootdemo;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
GreetingController¶
package com.example.jxspringbootdemo;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
Test application¶
Re-Install with Nexus¶
myvalues.yaml¶
Our application didn't work because now we have an application that depends on a Maven repository. We have to "re-install" Jenkins X, to have it install Nexus for us in the cdx
namespace.
Install¶
Make sure you execute this command where you have the myvalues.yaml
file.
jx install \
--provider $PROVIDER \
--external-ip $LB_IP \
--domain serverless.$DOMAIN \
--default-admin-password=admin \
--ingress-namespace $INGRESS_NS \
--ingress-deployment $INGRESS_DEP \
--default-environment-prefix tekton \
--git-provider-kind github \
--namespace ${INSTALL_NS} \
--prow \
--docker-registry gcr.io \
--docker-registry-org $PROJECT \
--tekton \
--kaniko \
-b
Test Application¶
To trigger a new build, make a change - for example to the README.md
and push it.
Configure TLS¶
Re-test application¶
jx update webhooks --repo=jx-cdx-spring-boot-demo-1 --org=${ORG}
jx get applications
jx get activity -f jx-cdx-spring-boot-demo-1 -w
http https://jx-cdx-spring-boot-demo-1.cdx-staging.serverless.${DOMAIN}/greeting