Jenkins+Gitea+ArgoCD+Kubernetes构建CI/CD流水线
1:环境
程序 | 版本 |
---|---|
Kubernetes | 1.23.3 |
Jenkins | 2.332.1 |
Gitea(因为内存不够,所以哦代替了Gitlab) | 1.15.9 |
ArgoCD | 2.3.3 |
Harbor | 2.4.1 |
2:部署所需环境
2.1:部署Kubernetes+ArgoCD
https://www.cnblogs.com/devopsdu/articles/kubeadm_containerd_argo.html
2.2:部署Jenkins and Gtiea
https://www.cnblogs.com/devopsdu/articles/kubernetes_devops.html
2.3:Harbor仓库部署
https://www.cnblogs.com/devopsdu/articles/kubernetes_harbor.html
3:确定基本环境
[root@k8s-master ~]# kubectl get pod,svc -n argocd
NAME READY STATUS RESTARTS AGE
pod/argocd-application-controller-0 1/1 Running 0 30h
pod/argocd-applicationset-controller-79f97597cb-mwzld 1/1 Running 0 30h
pod/argocd-dex-server-6fd8b59f5b-zx76f 1/1 Running 0 30h
pod/argocd-notifications-controller-5549f47758-2rgjk 1/1 Running 0 30h
pod/argocd-redis-79bdbdf78f-xhd8f 1/1 Running 0 30h
pod/argocd-repo-server-5569c7b657-t5ftv 1/1 Running 0 30h
pod/argocd-server-664b7c6878-9tjlh 1/1 Running 0 30h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/argocd-applicationset-controller ClusterIP 200.1.73.127 <none> 7000/TCP 30h
service/argocd-dex-server ClusterIP 200.1.77.207 <none> 5556/TCP,5557/TCP,5558/TCP 30h
service/argocd-metrics ClusterIP 200.1.88.62 <none> 8082/TCP 30h
service/argocd-notifications-controller-metrics ClusterIP 200.1.185.23 <none> 9001/TCP 30h
service/argocd-redis ClusterIP 200.1.5.40 <none> 6379/TCP 30h
service/argocd-repo-server ClusterIP 200.1.249.26 <none> 8081/TCP,8084/TCP 30h
service/argocd-server NodePort 200.1.15.59 <none> 80:31715/TCP,443:30604/TCP 30h
service/argocd-server-metrics ClusterIP 200.1.216.113 <none> 8083/TCP 30h
[root@k8s-master ~]# kubectl get pod,svc -n jenkins
NAME READY STATUS RESTARTS AGE
pod/jenkins-578bf5f66d-jtlsn 1/1 Running 0 5h4m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/jenkins NodePort 200.1.144.246 <none> 8080:30000/TCP,50000:31241/TCP 5h8m
[root@k8s-master ~]# kubectl get pod,svc -n gitea
NAME READY STATUS RESTARTS AGE
pod/gitea-b99456844-wq6c9 1/1 Running 0 2d2h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gitea NodePort 200.1.105.64 <none> 3000:31179/TCP,22:32235/TCP 2d2h
[root@k8s-registry harbor]# docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
harbor-core "/harbor/entrypoint.…" core running (healthy)
harbor-db "/docker-entrypoint.…" postgresql running (healthy)
harbor-jobservice "/harbor/entrypoint.…" jobservice running (healthy)
harbor-log "/bin/sh -c /usr/loc…" log running (healthy) 127.0.0.1:1514->10514/tcp
harbor-portal "nginx -g 'daemon of…" portal running (healthy)
nginx "nginx -g 'daemon of…" proxy running (healthy) 0.0.0.0:80->8080/tcp, 0.0.0.0:443->8443/tcp, :::80->8080/tcp, :::443->8443/tcp
redis "redis-server /etc/r…" redis running (healthy)
registry "/home/harbor/entryp…" registry running (healthy)
registryctl "/home/harbor/start.…" registryctl running (healthy)
4:操作Gitea创建不同环境仓库
因为我这里有所以我就不创建了,# 这里我没有对ci和cd的仓库分开
git clone下来仓库上传一下代码
[root@k8s-master demo]# tree flask-web-dev/
flask-web-dev/
dockerfile
project.tar.gz
yaml
flask-web.yaml
[root@k8s-master demo]# tree flask-web-test/
flask-web-test/
dockerfile # 构建项目镜像的Dockerfile
project.tar.gz # 项目代码
yaml # 部署项目的yaml目录
flask-web.yaml # 项目yaml
# 推送代码到仓库
[root@k8s-master demo]# cd flask-web-dev/
[root@k8s-master flask-web-dev]# git add .
[root@k8s-master flask-web-dev]# git commit -m "motify yaml"
[master 2158616] motify yaml
1 file changed, 0 insertions(+), 0 deletions(-)
[root@k8s-master flask-web-dev]# git push origin master
Username for 'http://10.0.0.10:31179': devops
Password for 'http://devops@10.0.0.10:31179':
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 430 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: . Processing 1 references
remote: Processed 1 references in total
To http://10.0.0.10:31179/devops/flask-web-dev.git
0abd8db..2158616 master -> master
[root@k8s-master flask-web-dev]# cd ../flask-web-test/
[root@k8s-master flask-web-test]# git add .
[root@k8s-master flask-web-test]# git commit -m "motify yaml"
[master ad4544a] motify yaml
1 file changed, 0 insertions(+), 0 deletions(-)
[root@k8s-master flask-web-test]# git push origin master
Username for 'http://10.0.0.10:31179': devops
Password for 'http://devops@10.0.0.10:31179':
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 430 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: . Processing 1 references
remote: Processed 1 references in total
To http://10.0.0.10:31179/devops/flask-web-test.git
7dd8a49..ad4544a master -> master
5:配置Jenkins流水线
# Jenkins需要结合Kubernetes (在前面链接有讲)
# pipline如下
# dev环境
def registry = "registry.kubernetes-devops.cn" # 定义镜像仓库变量
def project = "flask-web-dev" # 定义仓库路径变量
def app_name = "flask" # 定义镜像名称变量
def label = "dev" # 定义Label变量
def image_name = "${registry}/${project}/${app_name}:${label}" # 定义镜像名称变量
def git_address = "http://10.0.0.10:31179/devops/flask-web-dev.git" # 定义git仓库地址变量
def secret_name = "harbor" # 定义jenkins-slave拉取镜像的认证secret变量
def docker_registry_auth = "9df660fe-6e18-4223-b8b3-cbc60c8cd29d" # 定义镜像仓库账号密码变量 前提需要创建出来
def git_auth = "4221b986-141f-4609-bd5d-7612232cdfd8" # 定义Git仓库账号密码变量 前提需要创建出来
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
metadata:
name: jenkins-slave
namespace: jenkins
spec:
imagePullSecrets:
- name: ${secret_name}
containers:
- name: jnlp
image: "registry.kubernetes-devops.cn/library/slave:latest"
volumeMounts:
- name: docker-command
mountPath: /usr/bin/docker
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: docker-command
hostPath:
path: /usr/bin/docker
- name: docker-sock
hostPath:
path: /var/run/docker.sock
'''
}
}
stages {
stage('拉取代码'){
steps {
checkout([$class: 'GitSCM',
doGenerateSubmoduleConfigurations: false,
extensions: [], submoduleCfg: [],
userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]
])
}
}
stage('构建镜像并推送仓库') {
steps {
withCredentials([usernamePassword(credentialsId: "${docker_registry_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh """
docker build -t ${image_name} .
docker login -u ${username} -p '${password}' ${registry}
docker push ${image_name}
"""
}
}
}
}
}
# Test环境
def registry = "registry.kubernetes-devops.cn"
def project = "flask-web-test"
def app_name = "flask"
def label = "test"
def image_name = "${registry}/${project}/${app_name}:${label}"
def git_address = "http://10.0.0.10:31179/devops/flask-web.git"
def secret_name = "harbor"
def docker_registry_auth = "9df660fe-6e18-4223-b8b3-cbc60c8cd29d"
def git_auth = "4221b986-141f-4609-bd5d-7612232cdfd8"
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
metadata:
name: jenkins-slave
namespace: jenkins
spec:
imagePullSecrets:
- name: ${secret_name}
containers:
- name: jnlp
image: "registry.kubernetes-devops.cn/library/slave:latest"
volumeMounts:
- name: docker-command
mountPath: /usr/bin/docker
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: docker-command
hostPath:
path: /usr/bin/docker
- name: docker-sock
hostPath:
path: /var/run/docker.sock
'''
}
}
stages {
stage('拉取代码'){
steps {
checkout([$class: 'GitSCM',
doGenerateSubmoduleConfigurations: false,
extensions: [], submoduleCfg: [],
userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]
])
}
}
stage('构建镜像并推送仓库') {
steps {
withCredentials([usernamePassword(credentialsId: "${docker_registry_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
sh """
docker build -t ${image_name} .
docker login -u ${username} -p '${password}' ${registry}
docker push ${image_name}
"""
}
}
}
}
}
6:创建对应的镜像仓库
7:创建ArgoCD对应的应用
创建对应环境的仓库,如果不会创建可以参考以下文章:
https://www.cnblogs.com/devopsdu/articles/ArgoCD_deploy_use.html
创建完成,我们就可以在Jenkins构建了
细心的朋友就会发现,为什么我的时间不对,这是因为我没有做时间同步,所以时间是对不上的
8:ArgoCD构建项目
[root@k8s-master yaml]# kubectl get pod,svc -n dev
NAME READY STATUS RESTARTS AGE
pod/flask-b8b9d96c-6sb7d 1/1 Running 0 8m43s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/flask NodePort 200.1.113.17 <none> 80:30129/TCP 8m43s
[root@k8s-master yaml]# kubectl get pod,svc -n test
NAME READY STATUS RESTARTS AGE
pod/flask-656fdb7b79-5mmfb 1/1 Running 0 8m44s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/flask NodePort 200.1.203.244 <none> 80:32008/TCP 8m44s
# 到这儿,我们的项目就部署完成了,我们可以测试访问下