Jenkins on Kubernetes¶
Goal¶
Run Jenkins as best as we can on Kubernetes, taking as much advantage of the platform and ecosystem as we can.
Steps to take¶
- install LDAP
- install and configure Apache Keycloak backed by LDAP
- install Hashicorp Vault
- install Jenkins
- configure Jenkins with Jenkins Configuration as Code
- verify we can use Kubernetes agents
- verify we can use GitHub integration
- expose Telemtry via OpenTelemetry
- collect telemtry via Prometheus/Grafana
- collect telemtry via Tanzu Observability
LDAP¶
helm upgrade --install ldap helm-openldap/openldap --namespace keycloak --values ldap-values.yaml --version 2.0.4
Keycloak¶
helm upgrade --install keycloak bitnami/keycloak --namespace keycloak --values keycloak-values.yaml --version 9.2.8
Keycloak HTTPProxy¶
export LB_IP=$(kubectl get svc -n tanzu-system-ingress envoy -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cfssl gencert -ca ca.pem -ca-key ca-key.pem \
-config cfssl.json \
-profile=server \
-cn="${KEYCLOAK_HOSTNAME}" \
-hostname="${KEYCLOAK_HOSTNAME},keycloak.keycloak.svc.cluster.local,keycloak,localhost" \
base-service-cert.json | cfssljson -bare keycloak-server
Jenkins¶
kubectl create secret docker-registry dockerhub-pull-secret \
--docker-username=${DH_USER} \
--docker-password=${DH_PASS} \
--docker-email=${DH_EMAIL} \
--namespace ${NS}
kubectl create secret generic github-token \
--from-literal=user="${GH_USER}" \
--from-literal=token="${GH_TOKEN}" \
--namespace ${NS}
kubectl create secret generic jenkins-admin \
--from-literal=user="${JENKINS_ADMIN_USER}" \
--from-literal=token="${JENKINS_ADMIN_PASS}" \
--namespace ${NS}
Install Jenkins Helm¶
Jenkins CasC¶
...
Jenkins HTTPProxy¶
export LB_IP=$(kubectl get svc -n tanzu-system-ingress envoy -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cfssl gencert -ca ca.pem -ca-key ca-key.pem \
-config cfssl.json \
-profile=server \
-cn="${JENKINS_HOSTNAME}" \
-hostname="${JENKINS_HOSTNAME},jenkins.jenkins.svc.cluster.local,jenkins,localhost" \
base-service-cert.json | cfssljson -bare jenkins-server
Kaniko To Harbor¶
kubectl create secret docker-registry harbor-registry-creds \
--docker-username=${HARBOR_USER} \
--docker-password=${HARBOR_PASS} \
--docker-server=${HARBOR_SERVER} \
--namespace jenkins
Checks API¶
- create Jenkins credentials for GitHub API
- ensure you have create a GitHub Server in Jenkins config
credentials:
system:
domainCredentials:
- credentials:
- string:
description: "github token"
id: "githubtoken"
scope: GLOBAL
secret: "{AQAAABAAAAAwDgut+8oOqmwh4qHohWO09AxFPsz78EXLrtoC4QEFr9nY8orwx/mcLaS11G831IDmO8Ftxs2QockuYPJveteneQ==}"
- usernamePassword:
description: "github-credentials"
id: "github-credentials"
password: "{AQAAABAAAAAwutoG/5mM+UqCYohxLLogZ7Dpd8lyfWh9MeAbNybMplhycx4Z17h1WgzQPQn0lHAM+mfHsufBMuRTwl79rnfk9g==}"
scope: GLOBAL
username: "joostvdg"
gitHubPluginConfig:
configs:
- credentialsId: "githubtoken"
name: "GitHub"
hookUrl: "https://jenkins.10.220.7.70.nip.io/github-webhook/"
Pipeline¶
- create credentials
githubtoken
of type secret text with the GitHub API Tokengithub-credentials
username and password -> github username and API Token
- create GitHub Org Job
- add plugin GitHub Branch Source?
Webhooks behind a firewall¶
- https://www.jenkins.io/blog/2019/01/07/webhook-firewalls/
- https://developer.ibm.com/tutorials/deliver-your-webhooks-without-worrying-about-firewalls/
docker pull quay.io/schabrolles/smeeclient:stable --platform linux/amd64
docker tag quay.io/schabrolles/smeeclient:stable harbor.10.220.7.70.nip.io/test/smeeclient:stable
docker push harbor.10.220.7.70.nip.io/test/smeeclient:stable
- SMEESOURCE
- HTTPTARGET
kubectl run smee-client -n jenkins --rm -i --tty --image harbor.10.220.7.70.nip.io/test/harbor.10.220.7.70.nip.io/test/smeeclient:stable \
--env=SMEESOURCE=
apiVersion: v1
kind: Pod
metadata:
name: smee-client
namespace: jenkins
labels:
app: smee-client
spec:
containers:
- name: smee-client
image: harbor.10.220.7.70.nip.io/test/smeeclient:stable
env:
- name: SMEESOURCE
value: "https://smee.io/TVjVEDxMHHQeNPDl"
- name: HTTPTARGET
value: "http://jenkins:8080/github-webhook/"
Thanos¶
TO¶
- https://github.com/bdekany/wavefront-otel-auto-instrumentation
- https://artifacthub.io/packages/helm/bitnami/wavefront
- https://docs.wavefront.com/opentelemetry_tracing.html
kubectl create secret generic to-api-token --from-literal=api-token="${TO_API_TOKEN}" --namespace ${TO_NAMESPACE}
projectPacific:
enabled: true
vspheretanzu:
enabled: true
wavefront:
url: https://vmware.wavefront.com
existingSecret: to-api-token
collector:
useDaemonset: true
apiServerMetrics: true
cadvisor:
enabled: true
logLevel: info
discovery:
annotationExcludes: []
tags:
datacenter: vbc-h20-62
project: vbc-h20
owner: joostvdg
kubeStateMetrics:
enabled: true
proxy:
replicaCount: 2
zipkinPort: 9411
args: --traceZipkinListenerPorts 9411 --otlpGrpcListenerPorts 4317 --otlpHttpListenerPorts 4318
kubectl -n wavefront patch svc wavefront-proxy --patch '{"spec": {"ports": [{"name":"oltphttp", "port": 4318, "protocol": "TCP"}, {"name":"oltpgrpc", "port": 4317, "protocol": "TCP"}]}}'
- patch Proxy deployment
- patch Proxy service
- https://docs.wavefront.com/opentelemetry_tracing.html
- https://docs.wavefront.com/proxies_configuring.html#proxy-file-paths
- https://github.com/jenkinsci/opentelemetry-plugin
- https://github.com/bdekany/wavefront-otel-auto-instrumentation/blob/main/README.md
- https://github.com/bdekany/wavefront-otel-auto-instrumentation
Vault¶
- https://learn.hashicorp.com/tutorials/vault/kubernetes-raft-deployment-guide?in=vault/kubernetes
- https://www.vaultproject.io/docs/platform/k8s/helm/configuration
- https://learn.hashicorp.com/tutorials/vault/kubernetes-raft-deployment-guide?in=vault/kubernetes#initialize-and-unseal-vault
- artifact hub: https://artifacthub.io/packages/helm/hashicorp/vault
Vault Helm Install¶
kubectl create secret docker-registry dockerhub-pull-secret \
--docker-username=${DH_USER} \
--docker-password=${DH_PASS} \
--docker-email=${DH_EMAIL} \
--namespace ${NS}
kubectl create secret generic oic-auth \
--from-literal=clientID="${KEYCLOAK_CLIENT_ID}" \
--from-literal=clientSecret="${KEYCLOAK_CLIENT_SECRET}" \
--from-literal=keycloakUrl=${KEYCLOAK_URL} \
--namespace jenkins
HTTPProxy¶
export LB_IP=$(kubectl get svc -n tanzu-system-ingress envoy -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cfssl gencert -ca ca.pem -ca-key ca-key.pem \
-config cfssl.json \
-profile=server \
-cn="${VAULT_HOSTNAME}" \
-hostname="${VAULT_HOSTNAME},vault.vault.svc.cluster.local,vault-ui.vault.svc.cluster.local,vault,vault-ui,localhost" \
base-service-cert.json | cfssljson -bare vault-server
Unsealing¶
TODO¶
Things to improve on.
- make credentials come from Vault
- make credentials come from Kubernetes
- OpenTelemtry
- Prometheus/Grafana/?
- TO?
- Jobs via SeedJob from JobDSL?
References¶
Last update: 2022-08-06 12:51:44