mirror of
https://github.com/Dannecron/netology-devops-gw-infra.git
synced 2025-12-25 15:22:36 +03:00
[stage-5] improve jenkins helm chart, add scripts for jenkins pipeline
This commit is contained in:
62
jenkins/ref.jenkinsfile
Normal file
62
jenkins/ref.jenkinsfile
Normal file
@@ -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
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
91
jenkins/tag.jenkinsfile
Normal file
91
jenkins/tag.jenkinsfile
Normal file
@@ -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
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Jenkins CI/CD main instance.
|
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 }}.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|||||||
6
k8s/helm/jenkins/templates/_helper.tpl
Normal file
6
k8s/helm/jenkins/templates/_helper.tpl
Normal file
@@ -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 -}}
|
||||||
@@ -3,7 +3,7 @@ apiVersion: networking.k8s.io/v1
|
|||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .Chart.Name }}-{{ .Values.environment }}-ingress
|
name: {{ .Chart.Name }}-{{ .Values.environment }}-ingress
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
annotations:
|
annotations:
|
||||||
kubernetes.io/ingress.class: nginx
|
kubernetes.io/ingress.class: nginx
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: devops-tools
|
name: {{ .Values.namespace }}
|
||||||
|
|||||||
8
k8s/helm/jenkins/templates/secret.yaml
Normal file
8
k8s/helm/jenkins/templates/secret.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: docker-config
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
data:
|
||||||
|
config.json: {{ include "docker_config" . | fromYaml | toJson | b64enc }}
|
||||||
@@ -7,14 +7,12 @@ rules:
|
|||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["*"]
|
resources: ["*"]
|
||||||
verbs: ["*"]
|
verbs: ["*"]
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: jenkins-admin
|
name: jenkins-admin
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
@@ -27,4 +25,17 @@ roleRef:
|
|||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: jenkins-admin
|
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 }}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .Chart.Name }}-{{ .Values.environment }}-main
|
name: {{ .Chart.Name }}-{{ .Values.environment }}-main
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- name: web
|
- name: web
|
||||||
@@ -16,7 +16,7 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .Chart.Name }}-{{ .Values.environment }}-main-np
|
name: {{ .Chart.Name }}-{{ .Values.environment }}-main-np
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
spec:
|
spec:
|
||||||
type: NodePort
|
type: NodePort
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
---
|
---
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: {{ .Chart.Name }}-{{ .Values.environment }}-main
|
app: {{ .Chart.Name }}-{{ .Values.environment }}-main
|
||||||
service: jenkins
|
service: jenkins
|
||||||
name: {{ .Chart.Name }}-{{ .Values.environment }}-main
|
name: {{ .Chart.Name }}-{{ .Values.environment }}-main
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
spec:
|
spec:
|
||||||
|
serviceName: jenkins
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
@@ -35,10 +36,12 @@ spec:
|
|||||||
- name: web
|
- name: web
|
||||||
containerPort: 8080
|
containerPort: 8080
|
||||||
- name: jnlp
|
- name: jnlp
|
||||||
containerPort: 50000
|
containerPort: 30000
|
||||||
env:
|
env:
|
||||||
- name: JENKINS_OPTS
|
- name: JENKINS_OPTS
|
||||||
value: "--prefix=/jenkins"
|
value: "--prefix=/jenkins"
|
||||||
|
- name: JENKINS_SLAVE_AGENT_PORT
|
||||||
|
value: '30000'
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
@@ -3,17 +3,15 @@ apiVersion: v1
|
|||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
name: jenkins-pv-volume
|
name: jenkins-pv-volume
|
||||||
labels:
|
|
||||||
type: local
|
|
||||||
spec:
|
spec:
|
||||||
storageClassName: manual
|
storageClassName: manual
|
||||||
claimRef:
|
claimRef:
|
||||||
name: jenkins-pv-claim
|
name: jenkins-pv-claim
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
capacity:
|
capacity:
|
||||||
storage: 10Gi
|
storage: 10Gi
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteMany
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /mnt/jenkins
|
path: /mnt/jenkins
|
||||||
nodeAffinity:
|
nodeAffinity:
|
||||||
@@ -31,11 +29,11 @@ apiVersion: v1
|
|||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: jenkins-pv-claim
|
name: jenkins-pv-claim
|
||||||
namespace: devops-tools
|
namespace: {{ .Values.namespace }}
|
||||||
spec:
|
spec:
|
||||||
storageClassName: local-storage
|
storageClassName: manual
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteOnce
|
- ReadWriteMany
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 3Gi
|
storage: 3Gi
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
environment: production
|
environment: production
|
||||||
|
namespace: ci-cd
|
||||||
|
|
||||||
image:
|
image:
|
||||||
name: jenkins/jenkins
|
name: jenkins/jenkins
|
||||||
@@ -11,3 +12,7 @@ resources:
|
|||||||
requests:
|
requests:
|
||||||
cpu: 500m
|
cpu: 500m
|
||||||
memory: 500Mi
|
memory: 500Mi
|
||||||
|
|
||||||
|
docker:
|
||||||
|
dockerHubUser: user
|
||||||
|
dockerHubPassword: pass
|
||||||
|
|||||||
63
readme.md
63
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
|
[репозиторий](https://github.com/Dannecron/parcel-example-neko)
|
||||||
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)
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
helm install simple-app k8s/helm/simple-app
|
helm upgrade -i simple-app k8s/helm/simple-app
|
||||||
```
|
```
|
||||||
или, если чарт уже задеплоен
|
|
||||||
```shell
|
|
||||||
helm upgrade simple-app k8s/helm/simple-app
|
|
||||||
```
|
|
||||||
* [atlantis](https://www.runatlantis.io)
|
|
||||||
|
|
||||||
```shell
|
#### kube-prometheus-stack
|
||||||
helm install --set "atlantis.config.github.user=<access_token>" --set "atlantis.config.github.token=<token_secret>" --set "atlantis.config.github.secret=<webhook_secret>" atlantis k8s/helm/atlantis
|
|
||||||
```
|
|
||||||
|
|
||||||
где `<access_token>`, `<token_secret>` - это данные персонального access-токена, созданного на github,
|
[helm-чарт](https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack)
|
||||||
а `<webhook_secret>` - строка, которая должна совпадать в конфигурации webhook и atlantis.
|
|
||||||
|
|
||||||
* [jenkins](https://www.jenkins.io/)
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
```shell
|
#### Atlantis
|
||||||
helm isntall jenkins k8s/helm/jenkins
|
|
||||||
```
|
[документация](https://www.runatlantis.io)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
helm upgrade -i --set "config.github.user=<access_token>" --set "config.github.token=<token_secret>" --set "config.github.secret=<webhook_secret>" atlantis k8s/helm/atlantis
|
||||||
|
```
|
||||||
|
|
||||||
|
где `<access_token>`, `<token_secret>` - это данные персонального access-токена, созданного на github,
|
||||||
|
а `<webhook_secret>` - строка, которая должна совпадать в конфигурации webhook и atlantis.
|
||||||
|
|
||||||
|
#### Jenkins
|
||||||
|
|
||||||
|
[документация](https://www.jenkins.io/)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
helm upgrade -i --set "docker.dockerHubUser=<dockerHubUser>" --set "docker.dockerHubPassword=<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).
|
||||||
|
|||||||
Reference in New Issue
Block a user