From 6c1f1756161b4f1a47f86640382854c37f5c8a08 Mon Sep 17 00:00:00 2001 From: dannc Date: Sat, 1 Apr 2023 11:53:06 +0700 Subject: [PATCH] [stage-5] improve jenkins helm chart, add scripts for jenkins pipeline --- jenkins/ref.jenkinsfile | 62 +++++++++++++ jenkins/tag.jenkinsfile | 91 +++++++++++++++++++ k8s/helm/jenkins/templates/NOTES.txt | 2 +- k8s/helm/jenkins/templates/_helper.tpl | 6 ++ k8s/helm/jenkins/templates/ingress.yaml | 2 +- k8s/helm/jenkins/templates/namespace.yaml | 2 +- k8s/helm/jenkins/templates/secret.yaml | 8 ++ .../jenkins/templates/service-account.yaml | 19 +++- k8s/helm/jenkins/templates/service.yaml | 4 +- .../{deployment.yaml => statefulset.yaml} | 9 +- k8s/helm/jenkins/templates/volume.yaml | 12 +-- k8s/helm/jenkins/values.yaml | 5 + readme.md | 65 ++++++++----- 13 files changed, 244 insertions(+), 43 deletions(-) create mode 100644 jenkins/ref.jenkinsfile create mode 100644 jenkins/tag.jenkinsfile create mode 100644 k8s/helm/jenkins/templates/_helper.tpl create mode 100644 k8s/helm/jenkins/templates/secret.yaml rename k8s/helm/jenkins/templates/{deployment.yaml => statefulset.yaml} (88%) diff --git a/jenkins/ref.jenkinsfile b/jenkins/ref.jenkinsfile new file mode 100644 index 0000000..67647ce --- /dev/null +++ b/jenkins/ref.jenkinsfile @@ -0,0 +1,62 @@ +repository="dannecron/parcel-example-neko" + +podTemplate( + label: 'app-image-builder', + cloud: 'kubernetes', + serviceAccount: 'jenkins-admin', + namespace: "ci-cd", + containers: [ + containerTemplate( + name: 'builder', + image: 'moby/buildkit:v0.11.5', + ttyEnabled: true, + privileged: true + ) + ], + volumes: [ + secretVolume(secretName: 'docker-config', mountPath: '/root/.docker') + ] +) { + node('app-image-builder') { + properties([ + pipelineTriggers([ + [ + $class: 'GenericTrigger', + genericVariables: [ + [key: 'ref', value: '$.ref'], + [key: 'commit', value: '$.after'] + ], + printContributedVariables: true, + printPostContent: true, + regexpFilterText: '$ref', + regexpFilterExpression: '^refs/heads/.+$', + token: 'push' + ] + ]) + ]) + + stage('build') { + def branchName = (ref =~ /^refs\/heads\/(.+)$/)[0][1] + + echo "checkout branch ${branchName}" + git credentialsId: 'github-key', + url: 'git@github.com:Dannecron/parcel-example-neko.git', + branch: branchName + + container('builder') { + def tag = 'latest' + + if (branchName != 'main') { + tag = "${branchName}" + } + + def image="${repository}:${tag}" + + echo "start building image ${image}" + sh """ + buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${image},push=true + """ + } + } + } +} diff --git a/jenkins/tag.jenkinsfile b/jenkins/tag.jenkinsfile new file mode 100644 index 0000000..a9f958c --- /dev/null +++ b/jenkins/tag.jenkinsfile @@ -0,0 +1,91 @@ +repository="dannecron/parcel-example-neko" + +podTemplate( + label: 'app-image-builder', + cloud: 'kubernetes', + serviceAccount: 'jenkins-admin', + namespace: "ci-cd", + containers: [ + containerTemplate( + name: 'builder', + image: 'moby/buildkit:v0.11.5', + ttyEnabled: true, + privileged: true + ), + containerTemplate( + name: 'deployer', + image: 'alpine/k8s:1.26.3', + ttyEnabled: true, + privileged: true, + command: 'cat' + ) + ], + volumes: [ + secretVolume(secretName: 'docker-config', mountPath: '/root/.docker') + ] +) { + node('app-image-builder') { + properties([ + pipelineTriggers([ + [ + $class: 'GenericTrigger', + genericVariables: [ + [key: 'ref', value: '$.ref'], + [key: 'refType', value: '$.ref_type'] + ], + printContributedVariables: true, + printPostContent: true, + regexpFilterText: '$refType', + regexpFilterExpression: '^tag$', + token: 'tag' + ] + ]) + ]) + + stage('build') { + def tagName = "$ref" + def image="${repository}:${tagName}" + + dir('app') { + echo "checkout tag ${tagName}" +// checkout scm: [ +// $class: 'GitSCM', +// userRemoteConfigs: [[ +// url: 'git@github.com:Dannecron/parcel-example-neko.git', +// credentialsId: 'github-key' +// ]], +// branches: [[name: "refs/tags/${tagName}"]]], +// poll: false + } +// +// container('builder') { +// dir ('app') { +// echo "start building image ${image}" +// sh """ +// buildctl build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=${image},push=true +// """ +// } +// } + } + + stage('deploy') { + def tagName = "$ref" + + dir('infra') { + echo 'checkout infra repo' + git credentialsId: 'github-key', + url: 'git@github.com:Dannecron/netology-devops-gw-infra.git', + branch: 'main' + } + + container('deployer') { + dir('infra') { + echo "start deploy with version ${tagName}" + sh """ + helm --namespace=default upgrade --set 'image.tag=${tagName}' simple-app k8s/helm/simple-app + """ + } + } + } + } +} diff --git a/k8s/helm/jenkins/templates/NOTES.txt b/k8s/helm/jenkins/templates/NOTES.txt index 85fc342..b37d04d 100644 --- a/k8s/helm/jenkins/templates/NOTES.txt +++ b/k8s/helm/jenkins/templates/NOTES.txt @@ -1,6 +1,6 @@ --------------------------------------------------------- Jenkins CI/CD main instance. -Deployed version {{ .Values.image.tag | default .Chart.AppVersion }}. +Deployed version {{ .Values.image.tag | default .Chart.AppVersion }} in namespace {{ .Values.namespace }}. --------------------------------------------------------- diff --git a/k8s/helm/jenkins/templates/_helper.tpl b/k8s/helm/jenkins/templates/_helper.tpl new file mode 100644 index 0000000..08e98b7 --- /dev/null +++ b/k8s/helm/jenkins/templates/_helper.tpl @@ -0,0 +1,6 @@ +{{- define "docker_config" -}} +{{ $auth := printf "%s:%s" .Values.docker.dockerHubUser .Values.docker.dockerHubPassword }} +auths: + "https://index.docker.io/v1/": + auth: {{ $auth | b64enc }} +{{- end -}} diff --git a/k8s/helm/jenkins/templates/ingress.yaml b/k8s/helm/jenkins/templates/ingress.yaml index bf505a1..dba80cb 100644 --- a/k8s/helm/jenkins/templates/ingress.yaml +++ b/k8s/helm/jenkins/templates/ingress.yaml @@ -3,7 +3,7 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ .Chart.Name }}-{{ .Values.environment }}-ingress - namespace: devops-tools + namespace: {{ .Values.namespace }} annotations: kubernetes.io/ingress.class: nginx spec: diff --git a/k8s/helm/jenkins/templates/namespace.yaml b/k8s/helm/jenkins/templates/namespace.yaml index 484aaf5..bde689a 100644 --- a/k8s/helm/jenkins/templates/namespace.yaml +++ b/k8s/helm/jenkins/templates/namespace.yaml @@ -2,4 +2,4 @@ apiVersion: v1 kind: Namespace metadata: - name: devops-tools + name: {{ .Values.namespace }} diff --git a/k8s/helm/jenkins/templates/secret.yaml b/k8s/helm/jenkins/templates/secret.yaml new file mode 100644 index 0000000..2197ce3 --- /dev/null +++ b/k8s/helm/jenkins/templates/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: docker-config + namespace: {{ .Values.namespace }} +data: + config.json: {{ include "docker_config" . | fromYaml | toJson | b64enc }} diff --git a/k8s/helm/jenkins/templates/service-account.yaml b/k8s/helm/jenkins/templates/service-account.yaml index 4a45623..4b9217f 100644 --- a/k8s/helm/jenkins/templates/service-account.yaml +++ b/k8s/helm/jenkins/templates/service-account.yaml @@ -7,14 +7,12 @@ rules: - apiGroups: [""] resources: ["*"] verbs: ["*"] - --- apiVersion: v1 kind: ServiceAccount metadata: name: jenkins-admin - namespace: devops-tools - + namespace: {{ .Values.namespace }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -27,4 +25,17 @@ roleRef: subjects: - kind: ServiceAccount name: jenkins-admin - namespace: devops-tools + namespace: {{ .Values.namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: jenkins-cluster-admin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: jenkins-admin + namespace: {{ .Values.namespace }} diff --git a/k8s/helm/jenkins/templates/service.yaml b/k8s/helm/jenkins/templates/service.yaml index 88fa2e3..82b2ce4 100644 --- a/k8s/helm/jenkins/templates/service.yaml +++ b/k8s/helm/jenkins/templates/service.yaml @@ -3,7 +3,7 @@ apiVersion: v1 kind: Service metadata: name: {{ .Chart.Name }}-{{ .Values.environment }}-main - namespace: devops-tools + namespace: {{ .Values.namespace }} spec: ports: - name: web @@ -16,7 +16,7 @@ apiVersion: v1 kind: Service metadata: name: {{ .Chart.Name }}-{{ .Values.environment }}-main-np - namespace: devops-tools + namespace: {{ .Values.namespace }} spec: type: NodePort ports: diff --git a/k8s/helm/jenkins/templates/deployment.yaml b/k8s/helm/jenkins/templates/statefulset.yaml similarity index 88% rename from k8s/helm/jenkins/templates/deployment.yaml rename to k8s/helm/jenkins/templates/statefulset.yaml index 6cc1e4e..ad11f77 100644 --- a/k8s/helm/jenkins/templates/deployment.yaml +++ b/k8s/helm/jenkins/templates/statefulset.yaml @@ -1,13 +1,14 @@ --- apiVersion: apps/v1 -kind: Deployment +kind: StatefulSet metadata: labels: app: {{ .Chart.Name }}-{{ .Values.environment }}-main service: jenkins name: {{ .Chart.Name }}-{{ .Values.environment }}-main - namespace: devops-tools + namespace: {{ .Values.namespace }} spec: + serviceName: jenkins replicas: 1 selector: matchLabels: @@ -35,10 +36,12 @@ spec: - name: web containerPort: 8080 - name: jnlp - containerPort: 50000 + containerPort: 30000 env: - name: JENKINS_OPTS value: "--prefix=/jenkins" + - name: JENKINS_SLAVE_AGENT_PORT + value: '30000' resources: {{- toYaml .Values.resources | nindent 12 }} volumeMounts: diff --git a/k8s/helm/jenkins/templates/volume.yaml b/k8s/helm/jenkins/templates/volume.yaml index 369875e..7f95f45 100644 --- a/k8s/helm/jenkins/templates/volume.yaml +++ b/k8s/helm/jenkins/templates/volume.yaml @@ -3,17 +3,15 @@ apiVersion: v1 kind: PersistentVolume metadata: name: jenkins-pv-volume - labels: - type: local spec: storageClassName: manual claimRef: name: jenkins-pv-claim - namespace: devops-tools + namespace: {{ .Values.namespace }} capacity: storage: 10Gi accessModes: - - ReadWriteOnce + - ReadWriteMany hostPath: path: /mnt/jenkins nodeAffinity: @@ -31,11 +29,11 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins-pv-claim - namespace: devops-tools + namespace: {{ .Values.namespace }} spec: - storageClassName: local-storage + storageClassName: manual accessModes: - - ReadWriteOnce + - ReadWriteMany resources: requests: storage: 3Gi diff --git a/k8s/helm/jenkins/values.yaml b/k8s/helm/jenkins/values.yaml index 6b328cb..00957fa 100644 --- a/k8s/helm/jenkins/values.yaml +++ b/k8s/helm/jenkins/values.yaml @@ -1,4 +1,5 @@ environment: production +namespace: ci-cd image: name: jenkins/jenkins @@ -11,3 +12,7 @@ resources: requests: cpu: 500m memory: 500Mi + +docker: + dockerHubUser: user + dockerHubPassword: pass diff --git a/readme.md b/readme.md index 1406a51..7adc3bf 100644 --- a/readme.md +++ b/readme.md @@ -66,32 +66,49 @@ ansible-playbook -i ansible/kubectl_init kubectl_init.yml ### Деплой сервисов -* [kube-prometheus-stack](https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack) +#### Приложение - ```shell - helm repo add prometheus-community https://prometheus-community.github.io/helm-charts - helm install monitoring prometheus-community/kube-prometheus-stack -f k8s/helm/kube-prometheus-stack/values.yml - ``` -* [приложение](https://github.com/Dannecron/parcel-example-neko) +[репозиторий](https://github.com/Dannecron/parcel-example-neko) - ```shell - helm install simple-app k8s/helm/simple-app - ``` - или, если чарт уже задеплоен - ```shell - helm upgrade simple-app k8s/helm/simple-app - ``` -* [atlantis](https://www.runatlantis.io) +```shell +helm upgrade -i simple-app k8s/helm/simple-app +``` - ```shell - helm install --set "atlantis.config.github.user=" --set "atlantis.config.github.token=" --set "atlantis.config.github.secret=" atlantis k8s/helm/atlantis - ``` - - где ``, `` - это данные персонального access-токена, созданного на github, - а `` - строка, которая должна совпадать в конфигурации webhook и atlantis. +#### kube-prometheus-stack -* [jenkins](https://www.jenkins.io/) +[helm-чарт](https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack) - ```shell - helm isntall jenkins k8s/helm/jenkins - ``` +```shell +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm upgrade -i monitoring prometheus-community/kube-prometheus-stack -f k8s/helm/kube-prometheus-stack/values.yml +``` + +#### Atlantis + +[документация](https://www.runatlantis.io) + +```shell +helm upgrade -i --set "config.github.user=" --set "config.github.token=" --set "config.github.secret=" atlantis k8s/helm/atlantis +``` + +где ``, `` - это данные персонального access-токена, созданного на github, +а `` - строка, которая должна совпадать в конфигурации webhook и atlantis. + +#### Jenkins + +[документация](https://www.jenkins.io/) + +```shell +helm upgrade -i --set "docker.dockerHubUser=" --set "docker.dockerHubPassword=" jenkins k8s/helm/jenkins +``` + +Необходимые плагины: +* [kubernetes](https://plugins.jenkins.io/kubernetes/) +* [generic webhook trigger](https://plugins.jenkins.io/generic-webhook-trigger/) + +Необходимая конфигурация: +* Автоматически прописывать `known_hosts` +* Добавить секрет с названием `github-key` с именем пользователя и ssh-ключом к github +* Настроить облачную конфигурацию воркеров для kubernetes и убрать запуск воркеров на master-ноде +* Создать новый pipeline-проект для обработки push-эвентов по всем git-веткам со скриптом [jenkins/ref.jenkinsfile](./jenkins/ref.jenkinsfile). +* Создать новый pipeline-проект для обработки создания git-тэгов со скриптом [jenkins/tag.jenkinsfile](./jenkins/tag.jenkinsfile).