From 256912c4843f18997983d246b1838875da5d817f Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Thu, 21 Nov 2019 13:36:03 +1100 Subject: [PATCH] jenkins --- jenkins/JenkinsFile | 12 ++++ jenkins/dockerfiles/dockerfile | 43 ++++++++++++++ jenkins/dockerfiles/jenkins-slave | 94 +++++++++++++++++++++++++++++++ jenkins/jenkins.deployment.yaml | 51 +++++++++++++++++ jenkins/jenkins.pv.yaml | 35 ++++++++++++ jenkins/jenkins.pvc.yaml | 25 ++++++++ jenkins/jenkins.rbac.yaml | 37 ++++++++++++ jenkins/jenkins.service.yaml | 21 +++++++ jenkins/readme.md | 49 ++++++++++++++++ 9 files changed, 367 insertions(+) create mode 100644 jenkins/JenkinsFile create mode 100644 jenkins/dockerfiles/dockerfile create mode 100644 jenkins/dockerfiles/jenkins-slave create mode 100644 jenkins/jenkins.deployment.yaml create mode 100644 jenkins/jenkins.pv.yaml create mode 100644 jenkins/jenkins.pvc.yaml create mode 100644 jenkins/jenkins.rbac.yaml create mode 100644 jenkins/jenkins.service.yaml create mode 100644 jenkins/readme.md diff --git a/jenkins/JenkinsFile b/jenkins/JenkinsFile new file mode 100644 index 0000000..fc5366c --- /dev/null +++ b/jenkins/JenkinsFile @@ -0,0 +1,12 @@ +node('jenkins-slave') { + + stage('test pipeline') { + sh(script: """ + echo "hello" + git clone https://github.com/marcel-dempers/docker-development-youtube-series.git + cd ./docker-development-youtube-series/golang + + docker build . -t test + """) + } +} \ No newline at end of file diff --git a/jenkins/dockerfiles/dockerfile b/jenkins/dockerfiles/dockerfile new file mode 100644 index 0000000..5ff5ec9 --- /dev/null +++ b/jenkins/dockerfiles/dockerfile @@ -0,0 +1,43 @@ +FROM openjdk:8-jdk + +RUN apt-get update -y && apt-get install -y curl sudo + +#Install docker +RUN curl -sSL https://get.docker.com/ | sh + +ARG user=jenkins +ARG group=jenkins +ARG uid=10000 +ARG gid=10000 + +ENV HOME /home/${user} +RUN groupadd -g ${gid} ${group} +RUN useradd -c "Jenkins user" -d $HOME -u ${uid} -g ${gid} -m ${user} +RUN usermod -aG docker ${user} +RUN usermod -aG sudo ${user} + +ARG VERSION=3.20 +ARG AGENT_WORKDIR=/home/${user}/agent + +RUN curl --create-dirs -sSLo /usr/share/jenkins/slave.jar https://repo.jenkins-ci.org/public/org/jenkins-ci/main/remoting/${VERSION}/remoting-${VERSION}.jar \ + && chmod 755 /usr/share/jenkins \ + && chmod 644 /usr/share/jenkins/slave.jar + +#docker compose cli +RUN curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +COPY jenkins-slave /usr/local/bin/jenkins-slave +RUN chmod 777 /usr/local/bin/jenkins-slave + +RUN echo 'jenkins ALL=(ALL) NOPASSWD:ALL'| sudo EDITOR='tee -a' visudo + +USER ${user} +ENV AGENT_WORKDIR=${AGENT_WORKDIR} +RUN mkdir /home/${user}/.jenkins && mkdir -p ${AGENT_WORKDIR} + +VOLUME /home/${user}/.jenkins +VOLUME ${AGENT_WORKDIR} +WORKDIR /home/${user} + +ENTRYPOINT ["/usr/local/bin/jenkins-slave"] \ No newline at end of file diff --git a/jenkins/dockerfiles/jenkins-slave b/jenkins/dockerfiles/jenkins-slave new file mode 100644 index 0000000..601de4b --- /dev/null +++ b/jenkins/dockerfiles/jenkins-slave @@ -0,0 +1,94 @@ +#!/usr/bin/env sh + +# The MIT License +# +# Copyright (c) 2015, CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# Usage jenkins-slave.sh [options] -url http://jenkins [SECRET] [AGENT_NAME] +# Optional environment variables : +# * JENKINS_TUNNEL : HOST:PORT for a tunnel to route TCP traffic to jenkins host, when jenkins can't be directly accessed over network +# * JENKINS_URL : alternate jenkins URL +# * JENKINS_SECRET : agent secret, if not set as an argument +# * JENKINS_AGENT_NAME : agent name, if not set as an argument +# * JENKINS_AGENT_WORKDIR : agent work directory, if not set by optional parameter -workDir + +if [ $# -eq 1 ]; then + + # if `docker run` only has one arguments, we assume user is running alternate command like `bash` to inspect the image + exec "$@" + +else + + # if -tunnel is not provided try env vars + case "$@" in + *"-tunnel "*) ;; + *) + if [ ! -z "$JENKINS_TUNNEL" ]; then + TUNNEL="-tunnel $JENKINS_TUNNEL" + fi ;; + esac + + # if -workDir is not provided try env vars + if [ ! -z "$JENKINS_AGENT_WORKDIR" ]; then + case "$@" in + *"-workDir"*) echo "Warning: Work directory is defined twice in command-line arguments and the environment variable" ;; + *) + WORKDIR="-workDir $JENKINS_AGENT_WORKDIR" ;; + esac + fi + + if [ -n "$JENKINS_URL" ]; then + URL="-url $JENKINS_URL" + fi + + if [ -n "$JENKINS_NAME" ]; then + JENKINS_AGENT_NAME="$JENKINS_NAME" + fi + + if [ -z "$JNLP_PROTOCOL_OPTS" ]; then + echo "Warning: JnlpProtocol3 is disabled by default, use JNLP_PROTOCOL_OPTS to alter the behavior" + JNLP_PROTOCOL_OPTS="-Dorg.jenkinsci.remoting.engine.JnlpProtocol3.disabled=true" + fi + + # If both required options are defined, do not pass the parameters + OPT_JENKINS_SECRET="" + if [ -n "$JENKINS_SECRET" ]; then + case "$@" in + *"${JENKINS_SECRET}"*) echo "Warning: SECRET is defined twice in command-line arguments and the environment variable" ;; + *) + OPT_JENKINS_SECRET="${JENKINS_SECRET}" ;; + esac + fi + + OPT_JENKINS_AGENT_NAME="" + if [ -n "$JENKINS_AGENT_NAME" ]; then + case "$@" in + *"${JENKINS_AGENT_NAME}"*) echo "Warning: AGENT_NAME is defined twice in command-line arguments and the environment variable" ;; + *) + OPT_JENKINS_AGENT_NAME="${JENKINS_AGENT_NAME}" ;; + esac + fi + + #TODO: Handle the case when the command-line and Environment variable contain different values. + #It is fine it blows up for now since it should lead to an error anyway. + + exec java $JAVA_OPTS $JNLP_PROTOCOL_OPTS -cp /usr/share/jenkins/slave.jar hudson.remoting.jnlp.Main -headless $TUNNEL $URL $WORKDIR $OPT_JENKINS_SECRET $OPT_JENKINS_AGENT_NAME "$@" +fi \ No newline at end of file diff --git a/jenkins/jenkins.deployment.yaml b/jenkins/jenkins.deployment.yaml new file mode 100644 index 0000000..56e44a1 --- /dev/null +++ b/jenkins/jenkins.deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: jenkins + labels: + name: jenkins + app: jenkins +spec: + replicas: 1 + selector: + matchLabels: + name: jenkins + template: + metadata: + labels: + app: jenkins + name: jenkins + name: jenkins + spec: + serviceAccountName: jenkins + containers: + - env: + - name: JAVA_OPTS + value: -Xmx2048m -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 + image: jenkins/jenkins #:lts-alpine + imagePullPolicy: IfNotPresent + name: jenkins + ports: + - containerPort: 8080 + protocol: TCP + - containerPort: 50000 + protocol: TCP + # resources: + # limits: + # cpu: "1" + # memory: 1Gi + # requests: + # cpu: "1" + # memory: 1Gi + volumeMounts: + - mountPath: /var/jenkins_home + name: jenkins + restartPolicy: Always + securityContext: + #fsGroup: 1000 + runAsUser: 0 + terminationGracePeriodSeconds: 30 + volumes: + - name: jenkins + persistentVolumeClaim: + claimName: jenkins-claim diff --git a/jenkins/jenkins.pv.yaml b/jenkins/jenkins.pv.yaml new file mode 100644 index 0000000..6d8ce74 --- /dev/null +++ b/jenkins/jenkins.pv.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: jenkins + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 2Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data" +# apiVersion: v1 +# kind: PersistentVolume +# metadata: +# name: jenkins +# #annotations: +# #pv.beta.kubernetes.io/gid: "1000" +# spec: +# capacity: +# storage: 5Gi +# accessModes: +# - ReadWriteOnce +# azureFile: +# secretName: storage-connection +# secretNamespace: jenkins +# shareName: {{ .Values.jenkins.azurefileshare }} +# readOnly: false +# claimRef: +# name: jenkins-pvc +# kind: PersistenVolumeClaim +# namespace: jenkins +# persistentVolumeReclaimPolicy: Retain \ No newline at end of file diff --git a/jenkins/jenkins.pvc.yaml b/jenkins/jenkins.pvc.yaml new file mode 100644 index 0000000..80eb33a --- /dev/null +++ b/jenkins/jenkins.pvc.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: jenkins-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + +# apiVersion: v1 +# kind: PersistentVolumeClaim +# metadata: +# name: jenkins-pvc +# namespace: jenkins +# spec: +# accessModes: +# - ReadWriteOnce +# resources: +# requests: +# storage: 5Gi +# storageClassName: default +# volumeName: jenkins \ No newline at end of file diff --git a/jenkins/jenkins.rbac.yaml b/jenkins/jenkins.rbac.yaml new file mode 100644 index 0000000..de1ea83 --- /dev/null +++ b/jenkins/jenkins.rbac.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: jenkins +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: jenkins +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["create","delete","get","list","patch","update","watch"] +- apiGroups: [""] + resources: ["pods/exec"] + verbs: ["create","delete","get","list","patch","update","watch"] +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get","list","watch"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: jenkins +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: jenkins +subjects: +- kind: ServiceAccount + name: jenkins + namespace: jenkins diff --git a/jenkins/jenkins.service.yaml b/jenkins/jenkins.service.yaml new file mode 100644 index 0000000..b7e8a5a --- /dev/null +++ b/jenkins/jenkins.service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: jenkins + labels: + app: jenkins +spec: + type: ClusterIP + ports: + - name: ui + port: 8080 + targetPort: 8080 + protocol: TCP + - name: slave + port: 50000 + protocol: TCP + - name: http + port: 80 + targetPort: 8080 + selector: + app: jenkins diff --git a/jenkins/readme.md b/jenkins/readme.md new file mode 100644 index 0000000..c7e2dc0 --- /dev/null +++ b/jenkins/readme.md @@ -0,0 +1,49 @@ +# Setting up Jenkins Agent + +After installing `kubernetes-plugin` for Jenkins +* Go to Manage Jenkins | Bottom of Page | Cloud | Kubernetes (Add kubenretes cloud) +* Fill out plugin values + * Name: kubernetes + * Kubernetes URL: https://kubernetes.default:443 + * Kubernetes Namespace: jenkins + * Credentials | Add | Jenkins (Choose Kubernetes service account option & Global + Save) + * Test Connection | Should be successful! If not, check RBAC permissions and fix it! + * Jenkins URL: http://jenkins + * Tunnel : jenkins:50000 + * Apply cap only on alive pods : yes! + * Add Kubernetes Pod Template + * Name: jenkins-slave + * Namespace: jenkins + * Labels: jenkins-slave (you will need to use this label on all jobs) + * Containers | Add Template + * Name: jnlp + * Docker Image: aimvector/jenkins-slave + * Command to run : + * Arguments to pass to the command: + * Allocate pseudo-TTY: yes + * Add Volume + * HostPath type + * HostPath: /var/run/docker.sock + * Mount Path: /var/run/docker.sock + * Timeout in seconds for Jenkins connection: 300 +* Save + +# Test a build + +To run docker commands inside a jenkins agent you will need a custom jenkins agent with docker-in-docker working. +Take a look and build the docker file in `./dockerfiles/jenkins-agent` +Push it to a registry and use it instead of above configured `* Docker Image: jenkins/jnlp-slave` +If you do not use the custom image, the below pipeline will not work because default `* Docker Image: jenkins/jnlp-slave` public image does not have docker ability. + +* Add a Jenkins Pipeline + +``` +node('jenkins-slave') { + + stage('unit-tests') { + sh(script: """ + docker run --rm alpine /bin/sh -c "echo hello world" + """) + } +} +```