Catatan perev.: ini adalah terjemahan dari artikel dari blog teknik Preply tentang bagaimana Anda dapat menggunakan konfigurasi sebagai kode untuk alat CI / CD populer seperti Jenkins.Di perusahaan kami, kami mencoba mengikuti praktik "Semuanya seperti kode", ini tidak hanya berlaku untuk sumber daya infrastruktur, tetapi juga untuk pemantauan, kerja Jenkins, dll. Dalam artikel ini, saya akan berbicara tentang bagaimana kami menggunakan praktik ini untuk menerapkan dan mendukung Jenkins. Dan ini tidak hanya berlaku untuk infrastruktur untuk server dan agen, tetapi juga untuk plug-in, akses, pekerjaan, dan banyak hal lainnya.Selain itu, dalam artikel ini kami akan mencoba menemukan jawaban untuk pertanyaan seperti:- Apakah Jenkins kita menjadi lebih stabil?
- Bisakah kita sering melakukan perubahan konfigurasi server dan pekerjaan?
- Apakah pembaruan Jenkins masih menyakitkan bagi kita?
- Bisakah kita mengendalikan semua perubahan kita?
- Bisakah kita dengan cepat mengembalikan Jenkins jika ada fakap?
pengantar
Biasanya, hal pertama yang terlintas dalam pikiran ketika menyebutkan frasa βalat DevOpsβ adalah sistem CI / CD. Misalnya, kami menggunakan Jenkins karena kami menjalankan ratusan tugas setiap hari, dan itu puluhan ribu build. Beberapa fitur yang kami gunakan di Jenkins tidak tersedia di sistem CI / CD lain atau memiliki fungsi terbatas.Kami ingin mengontrol Jenkins sepenuhnya dari kode, termasuk infrastruktur, konfigurasi, pekerjaan, dan plug-in. Kami mencoba menjalankan Jenkins di Kubernetes, tetapi tidak sesuai dengan kebutuhan kami, ditambah lagi tidak mudah untuk menskalakan karena arsitekturnya .Ini akan dibahasInfrastruktur untuk Jenkins
Kami menggunakan AWS dan mengonfigurasi seluruh infrastruktur menggunakan Terraform dan alat hash lainnya seperti Packer dan Vault .Seperti yang disebutkan sebelumnya, kami mencoba menggunakan Jenkins di Kubernetes dan menghadapi beberapa masalah dengan penskalaan PVC , sumber daya, dan arsitektur yang tidak dirancang dengan baik.Di sini, kami menggunakan sumber daya AWS yang biasa: instance EC2, sertifikat SSL, penyeimbang, Cloudfront, dll. Gambar OS ( AMI ) dikonfigurasi menggunakan Packer, yang terintegrasi sempurna dengan Terraform dan Vault.{
"variables": {
"aws_access_key": "{{vault `packer/aws_access_key_id` `key`}}",
"aws_secret_key": "{{vault `packer/aws_secret_access_key` `key`}}",
"aws_region": "{{vault `packer/aws_region` `key`}}",
"vault_token": "{{env `VAULT_TOKEN`}}"
},
"builders": [{
"access_key": "{{ user `aws_access_key` }}",
"secret_key": "{{ user `aws_secret_key` }}",
"region": "{{ user `aws_region` }}",
"type": "amazon-ebs",
"communicator": "ssh",
"ssh_username": "ubuntu",
"instance_type": "c5.xlarge",
"security_group_id": "sg-12345",
"iam_instance_profile": "packer-role-profile",
"ami_name": "packer-jenkins-master-{{timestamp}}",
"ami_description": "Jenkins master image",
"launch_block_device_mappings": [{
"device_name": "/dev/sda1",
"volume_size": 50,
"volume_type": "gp2",
"delete_on_termination": true
}],
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "ubuntu/images/*ubuntu-bionic-18.04-amd64-server-*",
"root-device-type": "ebs"
},
"owners": ["099720109477"],
"most_recent": true
}
}],
"provisioners": [{
"type": "shell",
"environment_vars": ["VAULT_TOKEN={{ user `vault_token` }}"],
"scripts": ["packer_bootstrap.sh"]
}]
}
Contoh konfigurasi OS image seperti apa yang terlihat di Packer.Pada gilirannya, file tersebut packer_bootstrap.sh
berisi seperangkat perintah yang menginstal perangkat lunak di dalam gambar. Sebagai contoh, kita dapat menginstal Docker, docker-compose dan vaultenv atau Datadog-agent untuk pemantauan. Mengenai infrastruktur untuk gambar ini, kita dapat menggunakan Terraform, Cloudformation, Pulumi atau bahkan Ansible.Berikut adalah contoh kemungkinan infrastruktur AWS untuk Jenkins.Pengguna masuk ke Jenkins melalui penyeimbang internal, dan kait Github sampai ke server melalui yang eksternal. Kami menggunakan integrasi Jenkins dengan GitHub, sehingga beberapa tautan server harus dapat diakses dari Internet. Ada banyak solusi berbeda di sini (misalnya, daftar putih untuk alamat IP , URL atau token, dll.), Dalam kasus kami, kami menggunakan kombinasi URL yang diizinkan dan validasi token.Jadi, setelah manipulasi yang kami lakukan, kami sudah memiliki infrastruktur siap pakai dengan gambar OS yang dirangkai, kemampuan untuk memantau dan mengakses ke toko rahasia perusahaan.
Kami menggunakan Docker untuk menginstal Jenkins dan plugin-nya
Hal berikutnya yang akan kita lakukan adalah menginstal Jenkins dan pluginsnya. Kami terus-menerus mengalami masalah dalam memperbarui plugin, jadi tujuan utamanya adalah untuk memiliki plug-in yang jelas dari plugins yang diinstal dan versi mereka dalam kode.Dan di sini Docker akan membantu kami, karena kami dapat mengambil gambar Docker yang sudah dipasang sebelumnya dan menggunakannya sebagai basis untuk konfigurasi kami.FROM jenkins/jenkins:2.215
ENV CASC_JENKINS_CONFIG /jenkins_configs
USER root
RUN apt update && \
apt install -y python3 python3-pip && \
pip3 install awscli jenkins-job-builder jjb-reactive-choice-param --no-cache-dir
USER jenkins
VOLUME /jenkins_configs
VOLUME /var/jenkins_home
COPY plugins.txt /usr/share/jenkins/ref/
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt
DockerfileDi dalam gambar Docker, beberapa paket diinstal seperti Job Builder, yang akan saya bahas nanti, repositori juga terdaftar dan plugin yang ditentukan dalam file diinstal plugins.txt
.Jenkins.instance.pluginManager.plugins.each{
plugin ->
println ("${plugin.getShortName()}:${plugin.getVersion()}")
}
Anda bisa mendapatkan daftar plugin yang terpasang di Jenkins dengan mengklik tautan https://our-jenkins-url/script
dan menyimpan output ke fileplugins.txt
. Akhirnya, konfigurasi untuk docker-compose, yang akan menjalankan Jenkins di Docker.version: "3"
services:
jenkins:
build: .
container_name: jenkins
restart: always
ports:
- "50000:50000"
- "8080:8080"
volumes:
- ./configs/:/jenkins_configs/:ro
- ./jenkins_home/:/var/jenkins_home/:rw
environment:
- VAULT_TOKEN
- GITHUB_TOKEN
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- JAVA_OPTS=-Xms4G -Xmx8G -Xloggc:/var/jenkins_home/gc-%t.log -XX:NumberOfGCLogFiles=5 -XX:+UseGCLogFileRotation -XX:GCLogFileSize=20m -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCCause -XX:+PrintTenuringDistribution -XX:+PrintReferenceGC -XX:+PrintAdaptiveSizePolicy -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:+ParallelRefProcEnabled -XX:+UseStringDeduplication -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:+UnlockDiagnosticVMOptions -XX:G1SummarizeRSetStatsPeriod=1
volumes:
configs:
driver: local
jenkins_home:
driver: local
Kami juga menggunakan vaultenv untuk memalsukan rahasia dari Vault.Perhatikan beberapa opsi Java yang membantu kami dalam pengumpulan sampah dan batasan sumber daya. Ini artikel yang sangat dingin sekitar tala Jenkins.Dan tentu saja, sekarang kita dapat menyebarkan salinan Jenkins secara lokal dan bereksperimen dengan server dan plugin versi baru. Sangat nyaman.Sekarang kami memiliki instalasi Jenkins dan plugin yang bersih, yang dapat dengan mudah diluncurkan di prod. Mari kita tambahkan lebih banyak konfigurasi untuknya.
Mengkonfigurasi plugin Jenkins sebagai Kode (JCaSC) untuk konfigurasi server
Secara umum, ada plugin yang disebut Jenkins Configuration as Code ( JCasC ), yang memungkinkan Anda untuk menyimpan konfigurasi server dalam format teks yang dapat dibaca manusia.Dengan menggunakan plugin ini, Anda dapat menjelaskan konfigurasi keamanan, akses, pengaturan untuk plugin, agen, tab, dan banyak lagi.Konfigurasi disajikan dalam format YAML dan dibagi menjadi 5 blok:- kredensial (deskripsi rahasia sistem)
- jenkins (pengaturan otorisasi dan cloud, pengaturan global, deskripsi agen, beberapa pengaturan keamanan dan tab)
- keamanan (pengaturan keamanan global, seperti skrip yang diizinkan)
- tool (konfigurasi untuk alat eksternal seperti git, allure, dll.)
- tidak terklasifikasi (pengaturan lain, seperti integrasi dengan Slack)

Plugin mendukung impor konfigurasi dari instalasi Jenkins yang ada.Selainitu, plugin menyediakan dukungan untuk berbagai penyedia rahasia , namun, dalam contoh ini kita hanya akan menggunakan variabel lingkungan.credentials:
system:
domainCredentials:
- credentials:
- usernamePassword:
description: "AWS credentials"
id: "aws-creds"
password: ${AWS_SECRET_ACCESS_KEY}
scope: GLOBAL
username: ${AWS_ACCESS_KEY_ID}
- string:
description: "Vault token"
id: "vault-token"
scope: GLOBAL
secret: ${VAULT_TOKEN}
...
Beginilah rahasia dapat diuraikan.Kami juga menggunakan plugin Amazon EC2 untuk meningkatkan agen di AWS, dan konfigurasinya juga dapat dijelaskan menggunakan plugin ini. Otorisasi matriks memungkinkan kita untuk mengkonfigurasi akses pengguna menggunakan kode.jenkins:
authorizationStrategy:
projectMatrix:
permissions:
- "Overall/Administer:ivan.a@example.org"
- "Credentials/View:petr.d@example.org"
...
clouds:
- amazonEC2:
cloudName: "AWS"
privateKey: ${EC2_PRIVATE_KEY}
region: "${AWS_REGION}"
templates:
- ami: "ami-12345678"
amiType:
unixData:
sshPort: "22"
connectionStrategy: PRIVATE_IP
deleteRootOnTermination: true
description: "jenkins_agent"
idleTerminationMinutes: "20"
instanceCapStr: "100"
minimumNumberOfInstances: 0
mode: EXCLUSIVE
numExecutors: 1
remoteAdmin: "jenkins"
remoteFS: "/home/jenkins"
securityGroups: "sg-12345678"
subnetId: "subnet-12345678"
type: C52xlarge
...
Deskripsi agen dan aksesPlugin mendukung beberapa hal lain yang kami gunakan. Dengan proses pengujian lokal Jenkins yang terorganisir dengan baik, Anda dapat secara efektif menemukan dan memperbaiki bug sebelum mereka berpotensi masuk ke penjualan Jenkins.Sekarang kita memiliki konfigurasi yang dapat direproduksi untuk server, itu tetap berlaku untuk kecil, yaitu - pekerjaan.
Kami menggunakan Job Builder untuk proyek gaya bebas
Ada beberapa cara untuk menciptakan pekerjaan gaya bebas di Jenkins:- menggunakan antarmuka web (cara termudah, melompat dan melanjutkan)
- langsung menggunakan API REST
- menggunakan plugin seperti Job DSL atau JJB wrapper
Jenkins Job Builder (JJB) memungkinkan Anda untuk mengonfigurasi pekerjaan menggunakan YAML atau JSON. Dan itu cukup nyaman, karena Anda dapat mengonfigurasi semua pekerjaan dan menyimpan statusnya di git bersyarat. Faktanya, kita dapat membangun proses CI / CD untuk alat CI / CD menggunakan JJB..
βββ config.ini
βββ jobs
β βββ Job1.yaml
β | ...
β βββ Job2.yaml
βββ scripts
βββ job1.sh
| ...
βββ job2.sh
Ini adalah bagaimana (disederhanakan) struktur konfigurasi pekerjaan pada FS terlihat- job:
name: Job1
project-type: freestyle
auth-token: mytoken
disabled: false
concurrent: false
node: jenkins_agent
triggers:
- timed: '0 3 * * *'
builders:
- shell:
!include-raw: ../scripts/job1.sh
Dan ini adalah bagaimana pekerjaan dalam file terlihat Job1.yaml
, langkah-langkah dalam skrip. job1.sh
File konfigurasi JJB juga terlihat sederhana.$ cat config.ini
[job_builder]
ignore_cache=True
exclude=jobs/Job2
[jenkins]
url=https://jenkins.example.org
user=some_user
password=some_password
$ jenkins-jobs --conf config.ini test -r jobs/
$ jenkins-jobs --conf config.ini update -r jobs/
Aplikasi perubahan baru dapat dengan mudah diluncurkan menggunakan perintahjenkins-jobs update
Sendiri, pengguna yang membuat token harus memiliki hak istimewa yang sesuai untuk membuat dan mengonfigurasi pekerjaan. Kami hanya perlu menerapkan satu pekerjaan inisialisasi (pekerjaan awal), yang akan menerapkan perubahan menggunakan JJB di Jenkins.Perlu disebutkan bahwa JJB bukan "peluru perak", karena beberapa plugin yang tidak terlalu populer tidak didukung. Namun, ini adalah alat yang sangat fleksibel untuk menyimpan pekerjaan dalam kode, termasuk dukungan makro .Ringkasan
Sekarang kita telah mencapai akhir artikel ini, saya ingin kembali ke awal dan menjawab pertanyaan yang diajukan di awal. Kita bisa menjawab "ya" untuk setiap pertanyaan yang diajukan.Dalam artikel ini, kami tidak menyelidiki seluk-beluk pengaturan teknologi tertentu atau cara mengkonfigurasi Jenkins dengan benar , kami hanya berbagi pengalaman kami, yang mungkin berguna bagi Anda juga.PS Dalam artikel saya sering menggunakan kata "pekerjaan" (dari bahasa Inggris "pekerjaan", "tugas"), bagi saya itu terdengar lebih akrab daripada "tugas" dalam konteks CI / CD secara umum atau Jenkins.