├── .github └── workflows │ ├── maven.yml │ └── minikube.yaml ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .travis.yml ├── Dockerfile ├── Dockerfile-multistage ├── Dockerfile-old ├── Dockerfile-package ├── Dockerfile-sw ├── HPA.md ├── LICENSE ├── README-old.md ├── README.md ├── argocd ├── README.md ├── namspace.yaml ├── springboot-devops-demo-argocd.yaml ├── springboot-devops-demo-dp.yaml └── springboot-devops-demo-svc.yaml ├── charts ├── .helmignore ├── Chart.yaml ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── ingress.yaml │ └── service.yaml └── values.yaml ├── flux ├── Makefile ├── cluster.yaml ├── helmfile.yaml ├── pre.sh └── springboot-devops-demo.yaml ├── gitea └── docker-compose-gitea.yml ├── gogs └── docker-compose-gogs.yml ├── istio ├── gateway.yaml └── virtual-service.yaml ├── jenkins ├── Jenkinsfile ├── Jenkinsfile-charts ├── Jenkinsfile-old └── admin-rbac.yaml ├── kaniko ├── Dockerfile-package ├── README.md └── build.yaml ├── local-skaffold.yaml ├── mvnw ├── mvnw.cmd ├── okteto-pipeline.yml ├── pics ├── config_jenkins_pipeline.png └── create_jenkins_pipeline.png ├── pom.xml ├── settings.xml ├── skaffold.yaml ├── sonarqube └── docker-compose-sonarqube.yml ├── spinnaker ├── spinnaker-manifest.yaml └── trigger-demo-dockerhub.json ├── springboot-devops-demo-argocd.yaml ├── springboot-devops-demo-okteto.yaml ├── springboot-devops-demo-sidecar.yaml ├── springboot-devops-demo.yaml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── k8s │ │ │ ├── K8sApplication.java │ │ │ └── controller │ │ │ └── HelloController.java │ └── resources │ │ └── application.properties └── test │ └── java │ └── com │ └── example │ └── k8s │ └── K8sApplicationTests.java └── test └── scripts ├── clean.sh ├── minikube.sh ├── pre.sh └── springboot-devops-demo.sh /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Units & Integrations & Release 2 | 3 | on: 4 | push: 5 | #schedule: 6 | # - cron: '0 21 * * *' 7 | branches: 8 | - master 9 | #- dev 10 | #pull_request: 11 | #branches: 12 | #- master 13 | #- dev 14 | 15 | jobs: 16 | maven: 17 | #name: Units & Integrations 18 | runs-on: ubuntu-latest 19 | if: github.event.repository.owner.id == github.event.sender.id 20 | #runs-on: ${{ matrix.os.name }} 21 | #strategy: 22 | #matrix: 23 | # syntax inspired from https://github.community/t5/GitHub-Actions/Using-a-matrix-defined-input-for-a-custom-action/m-p/32032/highlight/true#M988 24 | #os: 25 | #- {name: macos-latest, short: "macos" } 26 | #- {name: ubuntu-latest, short: "ubuntu" } 27 | #- {name: windows-latest, short: "windows" } 28 | 29 | steps: 30 | - name: Checkout repo 31 | uses: actions/checkout@v2 32 | 33 | - name: Set up JDK 1.8 34 | uses: actions/setup-java@v1 35 | with: 36 | java-version: 1.8 37 | 38 | - name: List env 39 | run: env 40 | 41 | - name: time 42 | run: | 43 | time=$(curl -s "http://quan.suning.com/getSysTime.do") 44 | echo -e "当前时间:$(echo "${time}" | awk -F '":"|","' '{print $2}')" 45 | 46 | - name: Cache maven build 47 | uses: actions/cache@v1 48 | with: 49 | path: ~/.m2/repository 50 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} 51 | restore-keys: | 52 | ${{ runner.os }}-maven- 53 | 54 | - name: Maven Compile 55 | run: mvn compile 56 | 57 | - name: Maven Testing 58 | run: mvn test 59 | # - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=hbstarjason_springboot-k8s-example 60 | 61 | - name: Package 62 | #run: mvn clean package -Dmaven.test.skip=true -s ./settings.xml # 使用aliyun maven源 63 | run: mvn -B clean package -DskipTests 64 | 65 | - name: Verify 66 | run: mvn -B clean verify -Pintegration-test 67 | #mvn clean verify -P sonar -Dsonar.login=XXXX 68 | 69 | - name: Creating Artifact 70 | run: mkdir staging && cp target/*.jar staging 71 | 72 | - name: Upload Artifact 73 | uses: actions/upload-artifact@v1 74 | with: 75 | name: springboot-devops-demo-jar-staging-${{github.sha}} 76 | #name: springboot-devops-demo-jar-${{matrix.os.short}}-${{github.sha}} 77 | path: staging 78 | 79 | - name: Create gitstats 80 | run: sudo apt-get update && sudo apt-get install gitstats gnuplot -y && gitstats . ./gitstats-springboot-devops-demo 81 | 82 | - name: Upload gitstats 83 | uses: actions/upload-artifact@v1 84 | with: 85 | name: gitstats-springboot-devops-demo-${{github.sha}} 86 | path: ./gitstats-springboot-devops-demo 87 | 88 | #- name: Lint Dockerfile 89 | # run: docker run --rm -i hadolint/hadolint < Dockerfile 90 | # https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices 91 | # https://github.com/hadolint/hadolint/blob/master/README.md 92 | # https://github.com/hadolint/hadolint/blob/master/docs/INTEGRATION.md#continuous-integration 93 | 94 | #- name: Lint Dockerfile 95 | # uses: brpaz/hadolint-action@master 96 | # with: 97 | # dockerfile: "Dockerfile" 98 | 99 | #- name: Build the Docker image 100 | # run: docker build . --file Dockerfile --tag hbstarjason/springboot-devops-demo:$(date +%s) 101 | 102 | - name: Build and push Docker image to Dockerhub 103 | uses: docker/build-push-action@v1.1.0 104 | with: 105 | username: ${{ secrets.DOCKER_USERNAME }} 106 | password: ${{ secrets.DOCKER_PASSWORD }} 107 | repository: hbstarjason/springboot-devops-demo 108 | tags: latest 109 | 110 | - name: Trivy Image 111 | run : | 112 | # wget https://github.com/aquasecurity/trivy/releases/download/v0.16.0/trivy_0.16.0_Linux-64bit.tar.gz 113 | # tar zxvf trivy_0.16.0_Linux-64bit.tar.gz 114 | # ./trivy hbstarjason/springboot-devops-demo 115 | docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ 116 | -v $HOME/Library/Caches:/root/.cache/ aquasec/trivy hbstarjason/springboot-devops-demo 117 | 118 | - name: Deploy to Heroku 119 | uses: akhileshns/heroku-deploy@v3.0.4 120 | with: 121 | heroku_api_key: ${{secrets.HEROKU_API_KEY}} 122 | heroku_app_name: "springboot-devops-demo" 123 | heroku_email: ${{secrets.HEROKU_EMAIL}} 124 | 125 | #- name: Show Error Logs 126 | #if: failure() 127 | #run: | 128 | #cat hs_err_pid* 129 | #rm hs_err_pid* 130 | 131 | 132 | # mvn dependency:tree ---查看当前项目的依赖树 133 | 134 | # mvn [clean] compile ---编译项目中的代码 135 | # mvn [clean] test ---执行项目的测试 136 | # mvn [clean] install/package ---打包一个项目生成jar文件,只包含编译后的java二进制文件 137 | # mvn [clean] verify 138 | # mvn [clean] site ---生成文档和报告、站点 139 | -------------------------------------------------------------------------------- /.github/workflows/minikube.yaml: -------------------------------------------------------------------------------- 1 | 2 | name: chart-deploy-ci 3 | 4 | on: 5 | pull_request: 6 | push: 7 | branches: 8 | - master 9 | tags: 10 | - 'v*' 11 | 12 | env: 13 | SCRIPTS_DIR: ./test/scripts 14 | LOG_DIR: /tmp/springboot-devops-demo 15 | jobs: 16 | build: 17 | runs-on: ubuntu-16.04 18 | # runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Prepare enviroment 22 | run: | 23 | bash ${SCRIPTS_DIR}/pre.sh 24 | mkdir -p ${LOG_DIR} 25 | - name: Start minikube 26 | run: bash ${SCRIPTS_DIR}/minikube.sh start > ${LOG_DIR}/minikube-start-log.txt 2>&1 & 27 | - name: Wating minikube ready 28 | run: bash ${SCRIPTS_DIR}/minikube.sh wait 29 | - name: Setup tunnel 30 | run: minikube tunnel --log_dir=${LOG_DIR} & 31 | - name: Install springboot-devops-demo Chart 32 | run: bash ${SCRIPTS_DIR}/springboot-devops-demo.sh 33 | - uses: actions/upload-artifact@v1.0.0 34 | if: always() 35 | with: 36 | name: logs 37 | path: /tmp/springboot-devops-demo 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hbstarjason/springboot-devops-demo/e0deb381be792ed97a84d88c91e9e592bdf75107/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 语言 2 | language: java 3 | jdk: 4 | - openjdk8 5 | 6 | sudo: false 7 | 8 | before_install: 9 | - chmod +x ./mvnw 10 | 11 | #env: 12 | # global: 13 | # - secure: "a87fdfcbc4f23e420996462816b2765d5281e694" 14 | # - COMMIT=${TRAVIS_COMMIT::7} 15 | 16 | # https://sonarcloud.io/ 17 | addons: 18 | sonarcloud: 19 | organization: "hbstarjason" 20 | token: 21 | #secure: "$SONAR_TOKEN" # Set in travis-ci.org dashboard 22 | secure: "12IdOqiqlOWLDd04BREP0PO4HG6KoJYU8YonDCkyi9MD9SNXR/VIl+7qc6W6UAvGaTdI0YFUTpTZmPM/rHs005JZy9iHip7NUcVIW5c9zg5E1kAmkm/vP7YYJd84PAdU68hEZMoGKM0RiKSOfzjhhqbpf7PBXzimYgGvz6tIidITr8zKES8T+nnwzTDtB3w7G69fD08LWQZA9ILPcYig0Ztjzzr+uZ4J4PqWRbsImOvDz3nyBd69huLyf33eLXfhqV3DKw5jYuhURYNbZAh+di/VVPEYrhvhgx6WuIWYGPJtflAkT5Sd8BwSLPLoaOthTcNcAHSBE6o564ZlNqh9Z9y8Srdq6qidP5r12LZs6kuO2LQCsU0SmzvnM5jnRFBpDna/NWa9dFjDSNVNt4rfN6yjn+73GKuhsraKaEavTnr5bkseBsVws7/uMiCyvS0BO96RuvI6YoxGgO1jnG7sAgVF5BloJZGye161pz6v9NoTv4tGUdKPMXT6VycnFIjZX4Wc2cMmDyTJDHEBEgJHZs83e3/AYHPNSLb9hxMsJNDaMkotuiV1FMPF3+XpxbxTlU7bUEhJI1kbdsDQ/LFtkRPn2ewqj/IgnjCO+OOZd5m/S2OuFgGQZMsithZCxQchpxsOsRsYIXd0mji36JYzoGOvkXiyFM601unWl5Qmquw=" 23 | #secure: "hhNOQBKY5hhHCM6DT7yvB1/svSqesvXuQjFKzMK2NIgLpDWg4c378i9Cxbp+OwwjDSdep5Q3PQp1oVzn98gyKlYsg4+gpxe/e9QMrhjDrxtwPrURe9CsGbDS7wPB4CnEdRAc53SUXz1GmMsvGuVxN0y8BIYQJ7FiWpujUyN38UmDEhd75CWl8PYLG6XNO48JfEJfqJfOFJ0Ahm0IyWHPCgi/4EbHhoGVZ9eLTfqJFbOh0WzZpPDuPoWnnXwe13OKB0R9DWK+OYPDlokZF8jZDlzkdiU9SDnw7LEoRsW8D5ISIAweSvO3n7GbXl5i7ejkiv+x59EUW/O3ZjwMltXkY6zZDfwgHufFQno9i9aRXdNvNSUOARnjRLzHvcMXfKHP4FKJ6MZUvcyBHDKpW0U6wva/0eNVoxuXAn9un45Op+VMVy7cilxd6de1tHSD0hLWrVz+trYOU8U2QL7ps0DdsEr4HW9Qt7KVooEPSF6HmVGknkUqNpjF5YifT4x0oEGWo0uClyZ1fYnOfN9ouklC8MadwGkWKjd5+bgdjwmucRFaaLW7w3AyqHdsGK77ii4aBc22yeDgMsrQH1h2u5Nk5HOXyT6L2QZnIvzTEKZo3GByh+i2gRb1VQwirq8Fhq1QRdvcA7kgvtZhcXX9mEpXz0bxAfKD+bVk9NHJrSfBvjQ=" 24 | 25 | #services: 26 | # - docker 27 | 28 | # 执行脚本 29 | script: 30 | - git clone https://github.com/hbstarjason/springboot-devops-demo 31 | - cd springboot-devops-demo 32 | - mvn test 33 | #- ./mvnw clean install -B 34 | - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=hbstarjason_springboot-devops-demo 35 | #- mvn clean package -Dmaven.test.skip=true 36 | 37 | 38 | after_failure: 39 | - export TITLE="Travis:$TRAVIS_JOB_ID -- build job is failed" 40 | - export TEXT=[datetime]:`date` 41 | 42 | # 通知 43 | notifications: 44 | email: 45 | recipients: 46 | - 305201518@qq.com 47 | on_success: change # default: change 48 | on_failure: always # default: always 49 | 50 | # 缓存 51 | cache: 52 | directories: 53 | - '$HOME/.m2/repository' 54 | - '$HOME/.sonar/cache' 55 | 56 | # 57 | #deploy: 58 | # provider: heroku 59 | # api_key: $HEROKU_API_KEY 60 | # app: nk-spring-boot-app 61 | 62 | #deploy: 63 | # provider: releases 64 | # api_key: 65 | # secure: 7f4dc45a19f742dce39cbe4d1e5852fb588593fd 66 | # file: app/build/outputs/apk/app-release.apk 67 | # skip_cleanup: true 68 | # on: 69 | # tags: true 70 | 71 | 72 | # http://www.ruanyifeng.com/blog/2017/12/travis_ci_tutorial.html 73 | 74 | # before_install 75 | # install 76 | # before_script 77 | # script 78 | # aftersuccess or afterfailure 79 | # [OPTIONAL] before_deploy 80 | # [OPTIONAL] deploy 81 | # [OPTIONAL] after_deploy 82 | # after_script 83 | 84 | # passed:运行成功,所有步骤的退出码都是0 85 | # canceled:用户取消执行 86 | # errored:before_install、install、before_script有非零退出码,运行会立即停止 87 | # failed :script有非零状态码 ,会继续运行 88 | 89 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8 2 | #FROM openjdk:8-jre-alpine 3 | 4 | ENV JAVA_OPTS=-javaagent:/usr/skywalking/agent/skywalking-agent.jar 5 | 6 | ADD target/k8s.jar /opt/app.jar 7 | 8 | #ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom”,"-jar","/opt/app.jar"] 9 | # CMD ["bash", "-c", "java ${JAVA_OPTS} -jar /opt/app.jar -Djava.security.egd=file:/dev/./urandom"] 10 | CMD ["bash", "-c", "java -jar /opt/app.jar -Djava.security.egd=file:/dev/./urandom"] 11 | -------------------------------------------------------------------------------- /Dockerfile-multistage: -------------------------------------------------------------------------------- 1 | ### https://docs.docker.com/develop/develop-images/multistage-build/ 2 | 3 | FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD 4 | COPY pom.xml /build/ 5 | COPY src /build/src/ 6 | WORKDIR /build/ 7 | RUN mvn -B clean package -DskipTests 8 | 9 | # FROM openjdk:8-jdk-alpine AS MAVEN_BUILD 10 | # COPY mvnw . 11 | # COPY .mvn .mvn 12 | # COPY pom.xml /build/ 13 | # COPY src /build/src/ 14 | # WORKDIR /build/ 15 | # RUN mvn -B clean package -DskipTests 16 | 17 | FROM openjdk:8 18 | #FROM openjdk:8-jre-alpine 19 | 20 | ENV JAVA_OPTS=-javaagent:/usr/skywalking/agent/skywalking-agent.jar 21 | #ADD target/k8s.jar /opt/app.jar 22 | COPY --from=MAVEN_BUILD /build/target/k8s.jar /opt/app.jar 23 | 24 | CMD ["bash", "-c", "java -jar /opt/app.jar -Djava.security.egd=file:/dev/./urandom"] 25 | -------------------------------------------------------------------------------- /Dockerfile-old: -------------------------------------------------------------------------------- 1 | FROM openjdk:8 2 | 3 | ADD target/k8s.jar /opt/app.jar 4 | 5 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/opt/app.jar"] 6 | -------------------------------------------------------------------------------- /Dockerfile-package: -------------------------------------------------------------------------------- 1 | FROM maven:3.5.0-jdk-8-alpine 2 | 3 | RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 4 | RUN echo 'Asia/Shanghai' >/etc/timezone 5 | 6 | WORKDIR /project 7 | ADD . /project 8 | 9 | #RUN mvn package -Dmaven.test.skip=true 10 | RUN mvn -B clean package -DskipTests 11 | CMD ["mvn"] 12 | 13 | # docker build -t hbstarjason/springboot-devops-demo:jar -f Dockerfile-package . 14 | # docker run hbstarjason/springboot-devops-demo:jar tail -f -------------------------------------------------------------------------------- /Dockerfile-sw: -------------------------------------------------------------------------------- 1 | # FROM openjdk:8 2 | FROM hbstarjason/sw-base:6.1.0 3 | 4 | ADD target/k8s.jar /opt/app.jar 5 | 6 | # ENTRYPOINT ["java","-javaagent:/usr/skywalking/agent/skywalking-agent.jar -Dskywalking.agent.service_name=k8s-example -Djava.security.egd=file:/dev/./urandom”,"-jar","/opt/app.jar"] 7 | 8 | # CMD ["bash", "-c", "java -javaagent:/usr/skywalking/agent/skywalking-agent.jar -jar /opt/app.jar -Dskywalking.agent.service_name=k8s-example -Djava.security.egd=file:/dev/./urandom"] 9 | CMD ["bash", "-c", "java -javaagent:/usr/skywalking/agent/skywalking-agent.jar -jar /opt/app.jar -Djava.security.egd=file:/dev/./urandom"] 10 | -------------------------------------------------------------------------------- /HPA.md: -------------------------------------------------------------------------------- 1 | # HPA 2 | 3 | ```bash 4 | # https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/ 5 | 6 | $ kubectl apply -f https://raw.githubusercontent.com/hbstarjason/springboot-devops-demo/master/springboot-devops-demo.yaml 7 | deployment.apps/springboot-devops-demo created 8 | service/springboot-devops-demo created 9 | ingress.extensions/springboot-devops-demo created 10 | 11 | $ kubectl autoscale deployment springboot-devops-demo --cpu-percent=10 --min=1 --max=10 12 | horizontalpodautoscaler.autoscaling/springboot-devops-demo autoscaled 13 | 14 | $ kubectl get hpa 15 | NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE 16 | springboot-devops-demo Deployment/springboot-devops-demo /10% 1 10 3 23s 17 | 18 | $ kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://springboot-devops-demo:8080; done" 19 | 20 | $ kubectl get hpa 21 | NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE 22 | springboot-devops-demo Deployment/springboot-devops-demo 74%/10% 1 10 1 5m57s 23 | 24 | ### kubectl apply -f https://addons.kuboard.cn/metrics-server/0.3.7/metrics-server.yaml 25 | 26 | $ kubectl get deploy 27 | NAME READY UP-TO-DATE AVAILABLE AGE 28 | springboot-devops-demo 8/8 8 8 8m10s 29 | 30 | $ kubectl get deploy 31 | NAME READY UP-TO-DATE AVAILABLE AGE 32 | springboot-devops-demo 10/10 10 10 9m54s 33 | 34 | $ kubectl get hpa 35 | NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE 36 | springboot-devops-demo Deployment/springboot-devops-demo 20%/10% 1 10 10 11m 37 | 38 | 39 | ### minikube addons list 40 | ### minikube addons enable metrics-server 41 | ### helm install stable/metrics-server 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README-old.md: -------------------------------------------------------------------------------- 1 | # Jenkins CI/CD on Kubernetes 2 | 3 | 基于K8s的Jenkins CI/CD项目实战 4 | 5 | ## Jenkins创建项目 6 | ![create_project](pics/create_jenkins_pipeline.png) 7 | 8 | ## Jenkins项目配置 9 | ![config_project](pics/config_jenkins_pipeline.png) 10 | 11 | 12 | 参考文档: 13 | > [Jenkins CI/CD on Kubernetes部署配置](https://github.com/gjmzj/kubeasz/blob/master/docs/guide/jenkins.md) 14 | > [Kubernetes 拉取私有仓库镜像](https://blog.csdn.net/lusyoe/article/details/79587914) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot DevOps on Kubernetes 2 | 3 | **基于Kubernetes的Spring Boot DevOps项目实战** 4 | 5 | ### 涉及相关技术栈 6 | | | Public | Private | Note | 7 | | ---- | :----------------------------------------------: | ----------------------------------------------- | ------------------------------------------- | 8 | | 1 | / | VS code、skaffold | | 9 | | 2 | / | Docker | | 10 | | 3 | / | JIRA | | 11 | | 4 | / | Confluence | | 12 | | 5 | / | **Terraform**、Ansible | Infrastructure as Code | 13 | | 6 | Azure AKS、Amazon EKS、Google GCP | **Kubeadm**、Minikube、Kind、Kops、Openshift3.X | kubernetes | 14 | | 7 | **Github** | **Gitea**、Gogs、Gitlab | Git | 15 | | 8 | **Github Actions**、
**Travis-CI**、CircleCI | **Jenkins**、Gitlab-CI | Continuous Integration | 16 | | 9 | / | **Maven**、Gradle | | 17 | | 10 | / | **Nexus3**、JFrog Artifactory | | 18 | | 11 | **Dockerhub** | **Harbor** | Registry | 19 | | 12 | **SonarCloud** | **SonarQube** | | 20 | | 13 | / | **Helm**、**ArgoCD**、FluxCD | GitOps、Continuous Delivery | 21 | | 14 | / | **ArgoRollouts**、**Spinnaker**、Flagger | Progressive Delivery、Continuous Deployment | 22 | | 15 | / | Selenium | | 23 | | 16 | / | Jmeter | | 24 | | 17 | / | Istio | Service Mesh | 25 | | 18 | / | EFK(Elasticsearch+Fluentd+Kibana) | Logging | 26 | | 19 | / | **Prometheus && Alertmanager** | Monitoring && Alerting | 27 | | 20 | / | **Skywalking** | APM(Application Performance Management) | 28 | | 21 | / | Sentry | | 29 | 30 | ## DevOps ToolChain 31 | (图) 32 | 33 | ## User Guide 34 | 35 | 1. 提前安装好Jenkins,并且安装好kubernetes Plugin。 36 | 37 | 2. 安装好Kubernets集群,需要创建一个sa([admin-rbac.yaml](https://github.com/hbstarjason/springboot-devops-demo/blob/master/jenkins/admin-rbac.yaml)) 38 | 39 | 3. 在Jenkins里新建Pipeline Job,填写上git地址:[springboot-devops-demo](https://github.com/hbstarjason/springboot-devops-demo),“脚本地址”填写:jenkins/Jenkinsfile,保存执行Job,第一次Pipeline可能会报错,没关系,然后再次执行Job,填写上镜像仓库的相关信息。 40 | 41 | 4. 等待脚本自动运行完成CI部分。脚本会执行如下步骤: 42 | 43 | - Kubernetes Plugin 会在kubernetes集群上自动启动一个pod作为jenkins slave,这个pod启动后,会再自动启动多个container进行工作,执行完毕后,这个pod会自动被删除回收。 44 | - 第1个container是maven,根据checkout的git代码,进行maven pacakge。 45 | - 第2个container是docker,根据之前build出来的jar包进行docker build,docker push。 46 | - 第3个container是kubectl,执行kubectl apply -f *.yaml,目前已注释。 47 | - 第4个container是Helm,只执行Helm version,其他已注释。 48 | - 暂时缺少自动化测试步骤。(Jmeter、Selenium) 49 | - 其他container,随意可增加…… 50 | 51 | 5. CD部分有多种选择。 52 | 53 | - 直接通过kubectl或者Helm完成CD。(比较简单,不推荐!) 54 | 55 | - 通过ArgoCD进行GitOps完成CD。(Spinnaker亦可,FluxCD亦可) 56 | 57 | - 灰度发布有多种选择: 58 | 59 | a)通过Argo rollouts自动进行Canary、Blue/Green。 60 | 61 | b)通过Spinnaker+Promethues进行自动化Canary Analysis。 62 | 63 | c)通过Flagger+Nginx ingress/istio+Promethues进行自动化Canary。 64 | 65 | 6. SRE部分。 66 | 67 | - Logging,EFK(Elasticsearch+Fluentd+Kibana) 68 | - Monitoring && Alerting,Prometheus && Alertmanager 69 | - APM(Application Performance Management),Skywalking 70 | - Sentry 71 | 72 | ### 本地环境食用方法: 73 | 74 | - 使用Skaffold。 75 | 76 | ```bash 77 | # 安装kubernetes集群(此处省略) 78 | 79 | # 安装openjdk-8-jdk环境 80 | $ sudo apt-get update 81 | $ sudo apt-get install openjdk-8-jdk -y 82 | 83 | $ git clone https://github.com/hbstarjason/springboot-devops-demo && \ 84 | cd springboot-devops-demo 85 | $ mvn -B clean package -DskipTests 86 | $ skaffold dev 87 | 88 | # 直接能看到运行结果 89 | ``` 90 | 91 | - 直接使用kubectl。 92 | 93 | ```bash 94 | $ git clone https://github.com/hbstarjason/springboot-devops-demo && \ 95 | cd springboot-devops-demo 96 | $ kuebctl create ns springboot-devops-demo 97 | $ kubectl apply -f springboot-devops-demo.yaml -n springboot-devops-demo 98 | ``` 99 | 100 | - 使用Helm。 101 | 102 | ```bash 103 | $ git clone https://github.com/hbstarjason/springboot-devops-demo && \ 104 | cd springboot-devops-demo 105 | $ kubectl create ns springboot-devops-demo 106 | $ helm version 107 | version.BuildInfo{Version:"v3.2.4", GitCommit:"0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState:"clean", GoVersion:"go1.13.12"} 108 | $ helm install springboot-devops-demo ./charts/ -f ./charts/values.yaml --namespace springboot-devops-demo 109 | ``` 110 | 111 | - 一键部署至云端:猛击[![Develop on Okteto](https://okteto.com/develop-okteto.svg)](https://cloud.okteto.com/deploy?repository=https://github.com/hbstarjason/springboot-devops-demo),访问地址:https://springboot-devops-demo-hbstarjason.cloud.okteto.net/ 112 | 113 | ## History 114 | 115 | - 2021-02-28,增加Trivy对镜像进行扫描。 116 | - 2021-02-06,增加HPA部分。 117 | - 2020-12-23,增加多阶段构建。 118 | - 2020-10-01,增加Flux部分。 119 | - 2020-09-25,增加以Sidecar模式进行部署。 120 | - 2020-09-18,增加一键部署至云端(okteto.com),访问地址:https://springboot-devops-demo-hbstarjason.cloud.okteto.net/ 121 | - 2020-08-12,增加利用Github Actions自动安装Minikube,并采用Helm部署至Minikube进行验证测试。 122 | - 2020-07-20,完善ReadMe,增加使用Helm在本地环境直接运行。 123 | - 2020-07-15,增加本地开发环境食用方法,采用Skaffold一键部署。 124 | - 2020-07-15,增加使用ArgoCD部分。 125 | - 2020-07-14,完善ReadMe,增加User Guide。 126 | - 2020-07-11,增加利用Github Actions 自动发布到Heroku,访问地址:https://springboot-devops-demo.herokuapp.com/ 127 | - 2020-05-08,增加Travis-CI部分,集成SonarCloud。 128 | - Missing…… 129 | 130 | ## Reference 131 | 132 | >待定 1 133 | >待定 2 134 | >待定 3 135 | 136 | 137 | -------------------------------------------------------------------------------- /argocd/README.md: -------------------------------------------------------------------------------- 1 | Argo CD 安装请猛击:[Argocd-install.md](https://github.com/hbstarjason/Continuous-Deploy/blob/master/Argocd-install.md) 2 | 3 | 使用Argo CD自动部署本项目: 4 | 5 | - 使用Argo CLI自动部署 6 | 7 | ```bash 8 | ####### 提前安装好Argo CD 9 | ####### 提前下载好Argo CLI 10 | 11 | # 查看当前集群 12 | $ ./argocd-linux-amd64 cluster list 13 | SERVER NAME STATUS MESSAGE 14 | https://kubernetes.default.svc Successful 15 | 16 | # 添加本项目 17 | $ ./argocd-linux-amd64 app create springboot-devops-demo \ 18 | --repo https://github.com/hbstarjason/springboot-devops-demo.git \ 19 | --path argocd \ 20 | --dest-server https://kubernetes.default.svc \ 21 | --dest-namespace springboot-devops-demo 22 | 23 | ## --revision master 24 | ## --sync-policy automated 25 | ## --auto-prune 26 | 27 | # 部署本项目 28 | $ ./argocd-linux-amd64 app sync springboot-devops-demo 29 | # 开启--sync-policy automated,此步骤可省略 30 | 31 | # 查看并验证 32 | $ ./argocd-linux-amd64 app list 33 | 34 | ### 登录UI查看 35 | ``` 36 | 37 | - 使用CRD自动部署 38 | 39 | ```bash 40 | $ kubectl create ns springboot-devops-demo 41 | $ kubectl apply -f springboot-devops-demo-argocd.yaml 42 | 43 | ``` 44 | 45 | 46 | -------------------------------------------------------------------------------- /argocd/namspace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: springboot-devops-demo -------------------------------------------------------------------------------- /argocd/springboot-devops-demo-argocd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: springboot-devops-demo 5 | namespace: argocd 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/hbstarjason/springboot-devops-demo.git # what github repo to watch 10 | targetRevision: HEAD 11 | path: argocd # path to your deployment files 12 | directory: 13 | recurse: true # go through all the folders inside the path 14 | destination: 15 | server: https://kubernetes.default.svc # local cluster where argo is deployed 16 | namespace: springboot-devops-demo # which namespace to deploy to 17 | syncPolicy: 18 | automated: # roll out automatically when making changes 19 | prune: false 20 | selfHeal: false -------------------------------------------------------------------------------- /argocd/springboot-devops-demo-dp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: springboot-devops-demo 5 | labels: 6 | app: springboot-devops-demo 7 | tier: backend 8 | spec: 9 | replicas: 3 10 | selector: 11 | matchLabels: 12 | app: springboot-devops-demo 13 | tier: backend 14 | template: 15 | metadata: 16 | labels: 17 | app: springboot-devops-demo 18 | tier: backend 19 | spec: 20 | containers: 21 | - name: springboot-devops-demo 22 | image: hbstarjason/springboot-devops-demo 23 | resources: 24 | requests: 25 | cpu: 100m 26 | memory: 100Mi 27 | ports: 28 | - containerPort: 8080 29 | readinessProbe: 30 | httpGet: 31 | path: / 32 | port: 8080 33 | initialDelaySeconds: 10 34 | livenessProbe: 35 | httpGet: 36 | path: / 37 | port: 8080 38 | initialDelaySeconds: 15 -------------------------------------------------------------------------------- /argocd/springboot-devops-demo-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: springboot-devops-demo 5 | labels: 6 | app: springboot-devops-demo 7 | tier: backend 8 | spec: 9 | selector: 10 | app: springboot-devops-demo 11 | tier: backend 12 | ports: 13 | - port: 8080 14 | name: k8s-backend 15 | #type: LoadBalancer 16 | type: NodePort -------------------------------------------------------------------------------- /charts/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /charts/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "1.0" 3 | description: springboot-devops-demo helm chart 4 | name: springboot-devops-demo 5 | version: 1.0.0 6 | maintainers: 7 | - name: hbstarjason 8 | email: hbstarjason@gmail.com 9 | -------------------------------------------------------------------------------- /charts/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range .Values.ingress.hosts }} 4 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} 5 | {{- end }} 6 | {{- else if contains "NodePort" .Values.service.type }} 7 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "charts.fullname" . }}) 8 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 9 | echo http://$NODE_IP:$NODE_PORT 10 | {{- else if contains "LoadBalancer" .Values.service.type }} 11 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 12 | You can watch the status of by running 'kubectl get svc -w {{ template "charts.fullname" . }}' 13 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "charts.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 14 | echo http://$SERVICE_IP:{{ .Values.service.port }} 15 | {{- else if contains "ClusterIP" .Values.service.type }} 16 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "charts.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 17 | echo "Visit http://127.0.0.1:8080 to use your application" 18 | kubectl port-forward $POD_NAME 8080:80 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /charts/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "charts.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "charts.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "charts.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | -------------------------------------------------------------------------------- /charts/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ template "charts.fullname" . }} 5 | labels: 6 | app: {{ template "charts.name" . }} 7 | chart: {{ template "charts.chart" . }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | spec: 11 | replicas: {{ .Values.replicaCount }} 12 | selector: 13 | matchLabels: 14 | app: {{ template "charts.name" . }} 15 | release: {{ .Release.Name }} 16 | template: 17 | metadata: 18 | labels: 19 | app: {{ template "charts.name" . }} 20 | release: {{ .Release.Name }} 21 | spec: 22 | containers: 23 | - name: {{ .Chart.Name }} 24 | image: {{ .Values.image.repository | quote }} 25 | imagePullPolicy: {{ .Values.image.pullPolicy }} 26 | ports: 27 | - name: http 28 | containerPort: 8080 29 | protocol: TCP 30 | livenessProbe: 31 | httpGet: 32 | path: / 33 | port: http 34 | initialDelaySeconds: 15 35 | readinessProbe: 36 | httpGet: 37 | path: / 38 | port: http 39 | initialDelaySeconds: 10 40 | resources: 41 | {{ toYaml .Values.resources | indent 12 }} 42 | {{- with .Values.nodeSelector }} 43 | nodeSelector: 44 | {{ toYaml . | indent 8 }} 45 | {{- end }} 46 | {{- with .Values.affinity }} 47 | affinity: 48 | {{ toYaml . | indent 8 }} 49 | {{- end }} 50 | {{- with .Values.tolerations }} 51 | tolerations: 52 | {{ toYaml . | indent 8 }} 53 | {{- end }} 54 | -------------------------------------------------------------------------------- /charts/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "charts.fullname" . -}} 3 | {{- $ingressPath := .Values.ingress.path -}} 4 | apiVersion: extensions/v1beta1 5 | kind: Ingress 6 | metadata: 7 | name: {{ $fullName }} 8 | labels: 9 | app: {{ template "charts.name" . }} 10 | chart: {{ template "charts.chart" . }} 11 | release: {{ .Release.Name }} 12 | heritage: {{ .Release.Service }} 13 | {{- with .Values.ingress.annotations }} 14 | annotations: 15 | {{ toYaml . | indent 4 }} 16 | {{- end }} 17 | spec: 18 | {{- if .Values.ingress.tls }} 19 | tls: 20 | {{- range .Values.ingress.tls }} 21 | - hosts: 22 | {{- range .hosts }} 23 | - {{ . }} 24 | {{- end }} 25 | secretName: {{ .secretName }} 26 | {{- end }} 27 | {{- end }} 28 | rules: 29 | {{- range .Values.ingress.hosts }} 30 | - host: {{ . }} 31 | http: 32 | paths: 33 | - path: {{ $ingressPath }} 34 | backend: 35 | serviceName: {{ $fullName }} 36 | servicePort: http 37 | {{- end }} 38 | {{- end }} 39 | -------------------------------------------------------------------------------- /charts/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "charts.fullname" . }} 5 | labels: 6 | app: {{ template "charts.name" . }} 7 | chart: {{ template "charts.chart" . }} 8 | release: {{ .Release.Name }} 9 | heritage: {{ .Release.Service }} 10 | spec: 11 | type: {{ .Values.service.type }} 12 | ports: 13 | - port: {{ .Values.service.port }} 14 | targetPort: http 15 | protocol: TCP 16 | name: http 17 | selector: 18 | app: {{ template "charts.name" . }} 19 | release: {{ .Release.Name }} 20 | -------------------------------------------------------------------------------- /charts/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for charts. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: hbstarjason/springboot-devops-demo 9 | pullPolicy: IfNotPresent 10 | 11 | service: 12 | type: ClusterIP 13 | port: 80 14 | 15 | ingress: 16 | enabled: true 17 | annotations: {} 18 | # kubernetes.io/ingress.class: nginx 19 | # kubernetes.io/tls-acme: "true" 20 | path: / 21 | hosts: 22 | - springboot-devops-demo.com 23 | tls: [] 24 | # - secretName: chart-example-tls 25 | # hosts: 26 | # - chart-example.local 27 | 28 | resources: {} 29 | # We usually recommend not to specify default resources and to leave this as a conscious 30 | # choice for the user. This also increases chances charts run on environments with little 31 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 32 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 33 | # limits: 34 | # cpu: 100m 35 | # memory: 128Mi 36 | # requests: 37 | # cpu: 100m 38 | # memory: 128Mi 39 | 40 | nodeSelector: {} 41 | 42 | tolerations: [] 43 | 44 | affinity: {} 45 | -------------------------------------------------------------------------------- /flux/Makefile: -------------------------------------------------------------------------------- 1 | CLUSTER_NAME := fluxdemo 2 | OUTPUT_DIR := output 3 | KUBECONFIG := $(OUTPUT_DIR)/kubeconfig.yaml 4 | export KUBECONFIG 5 | 6 | .PHONY: all 7 | all: cluster 8 | 9 | .PHONY: check 10 | check: 11 | docker version 12 | kind version 13 | kubectl version --client 14 | helmfile --version 15 | fluxctl version 16 | 17 | .PHONY: cluster 18 | cluster: 19 | kind create cluster --name $(CLUSTER_NAME) --config cluster.yaml 20 | helmfile sync 21 | kubectl apply -f springboot-devops-demo.yaml 22 | kubectl rollout status deployment springboot-devops-demo 23 | 24 | .PHONY: logs-flux 25 | logs-flux: 26 | kubectl logs -f -lapp=flux 27 | 28 | .PHONY: delete-cluster 29 | delete-cluster: 30 | kind delete cluster --name $(CLUSTER_NAME) 31 | -rm $(KUBECONFIG) 32 | -------------------------------------------------------------------------------- /flux/cluster.yaml: -------------------------------------------------------------------------------- 1 | # https://kind.sigs.k8s.io/docs/user/quick-start/ 2 | 3 | kind: Cluster 4 | apiVersion: kind.x-k8s.io/v1alpha4 5 | nodes: 6 | - role: control-plane 7 | extraPortMappings: 8 | - containerPort: 30080 9 | hostPort: 30080 10 | protocol: TCP 11 | -------------------------------------------------------------------------------- /flux/helmfile.yaml: -------------------------------------------------------------------------------- 1 | repositories: 2 | - name: stable 3 | url: https://kubernetes-charts.storage.googleapis.com 4 | # url: http://mirror.azure.cn/kubernetes/charts 5 | - name: fluxcd 6 | url: https://charts.fluxcd.io 7 | 8 | releases: 9 | # https://github.com/fluxcd/flux/blob/master/chart/flux/README.md 10 | - name: flux 11 | chart: fluxcd/flux 12 | values: 13 | - git: 14 | url: git@github.com:hbstarjason/springboot-devops-demo.git 15 | path: flux 16 | pollInterval: 1m 17 | registry: 18 | includeImage: hbstarjason/springboot-devops-demo 19 | automationInterval: 1m 20 | 21 | # https://github.com/helm/charts/tree/master/stable/nginx-ingress 22 | - name: nginx-ingress 23 | chart: stable/nginx-ingress 24 | values: 25 | - controller: 26 | replicaCount: 1 27 | resources: 28 | limits: 29 | memory: 64Mi 30 | requests: 31 | memory: 64Mi 32 | service: 33 | type: NodePort 34 | nodePorts: 35 | http: 30080 36 | defaultBackend: 37 | replicaCount: 1 38 | resources: 39 | limits: 40 | memory: 16Mi 41 | requests: 42 | memory: 16Mi 43 | -------------------------------------------------------------------------------- /flux/pre.sh: -------------------------------------------------------------------------------- 1 | 2 | KUBECTLVERSION=v1.19.0 3 | KINDVERSION=v0.9.0 4 | HELMFILEVERSION=v0.130.0 5 | FLUXCTLVERSION=1.20.2 6 | HELMVERSION=helm-v3.2.4 7 | 8 | # https://kubernetes.io/zh/docs/tasks/tools/install-kubectl/ 9 | # curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl" 10 | curl -sSL "https://storage.googleapis.com/kubernetes-release/release/${KUBECTLVERSION}/bin/linux/amd64/kubectl" -o /tmp/kubectl && \ 11 | chmod +x /tmp/kubectl && \ 12 | sudo mv /tmp/kubectl /usr/local/bin/kubectl 13 | 14 | curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/${KINDVERSION}/kind-linux-amd64 && \ 15 | chmod +x ./kind && \ 16 | mv ./kind /usr/local/bin/kind 17 | 18 | wget https://github.com/roboll/helmfile/releases/download/${HELMFILEVERSION}/helmfile_linux_amd64 && \ 19 | chmod +x helmfile_linux_amd64 && \ 20 | mv helmfile_linux_amd64 /usr/local/bin/helmfile 21 | 22 | wget https://github.com/fluxcd/flux/releases/download/${FLUXCTLVERSION}/fluxctl_linux_amd64 && \ 23 | chmod +x fluxctl_linux_amd64 && \ 24 | mv fluxctl_linux_amd64 /usr/local/bin/fluxctl 25 | 26 | curl -sSL https://get.helm.sh/${HELMVERSION}-linux-amd64.tar.gz | \ 27 | sudo tar xz -C /usr/local/bin --strip-components=1 linux-amd64/helm -------------------------------------------------------------------------------- /flux/springboot-devops-demo.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: springboot-devops-demo 5 | labels: 6 | app: springboot-devops-demo 7 | tier: backend 8 | annotations: 9 | fluxcd.io/automated: "true" 10 | spec: 11 | replicas: 3 12 | selector: 13 | matchLabels: 14 | app: springboot-devops-demo 15 | tier: backend 16 | template: 17 | metadata: 18 | labels: 19 | app: springboot-devops-demo 20 | tier: backend 21 | spec: 22 | containers: 23 | - name: springboot-devops-demo 24 | image: hbstarjason/springboot-devops-demo 25 | resources: 26 | requests: 27 | cpu: 100m 28 | memory: 100Mi 29 | ports: 30 | - containerPort: 8080 31 | readinessProbe: 32 | httpGet: 33 | path: / 34 | port: 8080 35 | initialDelaySeconds: 10 36 | livenessProbe: 37 | httpGet: 38 | path: / 39 | port: 8080 40 | initialDelaySeconds: 15 41 | 42 | --- 43 | apiVersion: v1 44 | kind: Service 45 | metadata: 46 | name: springboot-devops-demo 47 | labels: 48 | app: springboot-devops-demo 49 | tier: backend 50 | spec: 51 | selector: 52 | app: springboot-devops-demo 53 | tier: backend 54 | ports: 55 | - port: 8080 56 | name: k8s-backend 57 | 58 | --- 59 | apiVersion: extensions/v1beta1 60 | kind: Ingress 61 | metadata: 62 | name: springboot-devops-demo 63 | spec: 64 | rules: 65 | - host: springboot-devops-demo-127-0-0-1.nip.io 66 | http: 67 | paths: 68 | - path: / 69 | backend: 70 | serviceName: springboot-devops-demo 71 | servicePort: k8s-backend 72 | 73 | 74 | -------------------------------------------------------------------------------- /gitea/docker-compose-gitea.yml: -------------------------------------------------------------------------------- 1 | 2 | ## https://docs.gitea.io/en-us/comparison/ 3 | ## https://docs.gitea.io/zh-cn/comparison/ 4 | 5 | 6 | 7 | #### https://docs.gitea.io/zh-cn/install-with-docker/ 8 | #### docker run -d --name=gitea -p 10022:22 -p 10080:3000 -v /var/lib/gitea:/data gitea/gitea:latest 9 | #### git clone ssh://git@hostname:10022/username/repo.git 10 | 11 | 12 | ### https://docs.gitea.io/en-us/install-with-docker/ 13 | 14 | version: "2" 15 | 16 | networks: 17 | gitea: 18 | external: false 19 | 20 | services: 21 | server: 22 | image: gitea/gitea:latest 23 | environment: 24 | - USER_UID=1000 25 | - USER_GID=1000 26 | restart: always 27 | networks: 28 | - gitea 29 | volumes: 30 | - ./gitea:/data 31 | - /etc/timezone:/etc/timezone:ro 32 | - /etc/localtime:/etc/localtime:ro 33 | ports: 34 | - "3000:3000" 35 | - "222:22" -------------------------------------------------------------------------------- /gogs/docker-compose-gogs.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | gogsdb: 4 | image: mysql:5.7 5 | container_name: gogsdb 6 | restart: always 7 | environment: 8 | MYSQL_DATABASE: gogs 9 | MYSQL_ROOT_PASSWORD: gogs 10 | MYSQL_USER: gogs 11 | MYSQL_PASSWORD: gogs 12 | volumes: 13 | - db_data:/var/lib/mysql_gogs 14 | ports: 15 | - "13306:3306" 16 | networks: 17 | - gogs-network 18 | 19 | gogsapp: 20 | depends_on: 21 | - gogsdb 22 | image: gogs/gogs 23 | container_name: gogsapp 24 | restart: always 25 | ports: 26 | - "322:22" 27 | - "3000:3000" 28 | volumes: 29 | - app_data:/data 30 | networks: 31 | - gogs-network 32 | volumes: 33 | db_data: 34 | app_data: 35 | networks: 36 | gogs-network: 37 | driver: bridge -------------------------------------------------------------------------------- /istio/gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: Gateway 3 | metadata: 4 | name: springboot-devops-demo 5 | spec: 6 | selector: 7 | istio: ingressgateway 8 | servers: 9 | - port: 10 | number: 80 11 | name: http 12 | protocol: HTTP 13 | hosts: 14 | - "springboot-devops-demo.hbstarjason.com" 15 | -------------------------------------------------------------------------------- /istio/virtual-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: springboot-devops-demo 5 | spec: 6 | hosts: 7 | - "springboot-devops-demo.hbstarjason.com" 8 | gateways: 9 | - springboot-devops-demo-gateway 10 | http: 11 | - match: 12 | - uri: 13 | prefix: / 14 | route: 15 | - destination: 16 | port: 17 | number: 8080 18 | host: k8s-example 19 | -------------------------------------------------------------------------------- /jenkins/Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | def projectProperties = [ 4 | [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '5']], 5 | parameters([ 6 | string(name: 'DOCKER_USER', defaultValue: '', description: 'docker用户名'), 7 | string(name: 'DOCKER_PASSWORD', defaultValue: '', description: 'docker用户密码'), 8 | string(name: 'REGISTRY_URL', defaultValue: 'docker.io', description: 'docker仓库地址') 9 | ]) 10 | ] 11 | 12 | properties(projectProperties) 13 | 14 | def label = "mypod-${UUID.randomUUID().toString()}" 15 | 16 | podTemplate(label: label, cloud: 'kubernetes', serviceAccount: 'admin', containers: [ 17 | containerTemplate(name: 'maven', image: 'maven:3.6.0-jdk-8', command: 'cat', ttyEnabled: true), 18 | //containerTemplate(name: 'maven', image: 'maven:3.6-alpine', command: 'cat', ttyEnabled: true), 19 | containerTemplate(name: 'docker', image: 'docker', command: 'cat', ttyEnabled: true), 20 | //containerTemplate(name: 'kubectl', image: 'cnych/kubectl', command: 'cat', ttyEnabled: true), 21 | //containerTemplate(name: 'kubectl', image: 'lachlanevenson/k8s-kubectl:v1.10.2', command: 'cat', ttyEnabled: true), 22 | //containerTemplate(name: 'kubectl', image: 'lachlanevenson/k8s-kubectl:v1.14.0', command: 'cat', ttyEnabled: true), 23 | containerTemplate(name: 'helm', image: 'cnych/helm', command: 'cat', ttyEnabled: true) 24 | ], 25 | volumes: [ 26 | hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'), 27 | //hostPathVolume(mountPath: '/root/.gradle', hostPath: '/home/gradle/.gradle'), 28 | //hostPathVolume(hostPath: '/root/.kube', mountPath: '/root/.kube'), 29 | hostPathVolume(hostPath: '/root/.m2', mountPath: '/root/.m2') 30 | ], 31 | annotations: [ 32 | podAnnotation(key: "sidecar.istio.io/inject", value: "false") 33 | ] 34 | 35 | ) { 36 | 37 | node(label) { 38 | 39 | def gitCommit 40 | def shortGitCommit 41 | def previousGitCommit 42 | 43 | container('maven') { 44 | 45 | stage('checkout') { 46 | checkout scm 47 | 48 | sh 'printenv' 49 | 50 | gitCommit = sh(script: "git rev-parse HEAD", returnStdout: true).trim() 51 | shortGitCommit = "${currentBuild.number}-${gitCommit[0..10]}" 52 | //shortGitCommit = "${gitCommit[0..10]}" 53 | previousGitCommit = sh(script: "git rev-parse ${gitCommit}~", returnStdout: true) 54 | 55 | echo "gitCommit = ${gitCommit}" 56 | echo "shortGitCommit = ${shortGitCommit}" 57 | echo "previousGitCommit = ${previousGitCommit}" 58 | } 59 | 60 | //https://jenkins.io/doc/pipeline/tour/tests-and-artifacts/ 61 | stage('pacakge') { 62 | 63 | sh 'mvn clean package -Dmaven.test.skip=true -s ./settings.xml' 64 | } 65 | //stage('Test') { 66 | // sh 'mvn test' 67 | //} 68 | 69 | } //post { 70 | // always { 71 | // junit 'build/reports/*.xml' 72 | // } 73 | // } 74 | 75 | container('docker') { 76 | 77 | stage('docker-login') { 78 | //REGISTRY_URL私有仓库地址,也可使用官方地址:docker.io 79 | sh "echo ${params.DOCKER_PASSWORD} | docker login -u ${params.DOCKER_USER} --password-stdin ${params.REGISTRY_URL} " 80 | //withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) 81 | //{ 82 | //sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}" 83 | //} 84 | } 85 | 86 | stage('docker-build') { 87 | sh "docker build . -t ${params.REGISTRY_URL}/${params.DOCKER_USER}/springboot-devops-demo:${shortGitCommit}" 88 | //sh "docker tag ${params.REGISTRY_URL}/${params.DOCKER_USER}/springboot-devops-demo:${shortGitCommit} ${params.REGISTRY_URL}/${params.DOCKER_USER}/springboot-devops-demo:latest" 89 | } 90 | 91 | stage('docker-push') { 92 | sh "docker push ${params.REGISTRY_URL}/${params.DOCKER_USER}/springboot-devops-demo:${shortGitCommit}" 93 | //sh "docker push ${params.REGISTRY_URL}/${params.DOCKER_USER}/springboot-devops-demo:latest" 94 | } 95 | 96 | stage('docker-remove') { 97 | sh "docker rmi ${params.REGISTRY_URL}/${params.DOCKER_USER}/springboot-devops-demo:${shortGitCommit}" 98 | } 99 | 100 | } 101 | 102 | 103 | //container('kubectl') { 104 | //stage('k8s deploy') { 105 | //sh "sed -i \"s/hbstarjason\\/springboot-devops-demo/${params.REGISTRY_URL}\\/${params.DOCKER_USER}\\/springboot-devops-demo:${shortGitCommit}/g\" springboot-devops-demo.yaml" 106 | //sh "kubectl --kubeconfig=/root/.kube/config apply -f springboot-devops-demo.yaml" 107 | //sh "kubectl create -f jenkins/admin-rbac.yaml" 108 | //sh "kubectl get ns |grep -w springboot-devops-demo || kubectl create ns springboot-devops-demo" 109 | //sh "kubectl apply -f springboot-devops-demo.yaml -n springboot-devops-demo" 110 | //kubectl get svc springboot-devops-demo -n springboot-devops-demo -o yaml |sed 's/ClusterIP/LoadBalancer/' |kubectl replace -f - 111 | //} 112 | // } 113 | 114 | 115 | container('helm') { 116 | stage('helm deploy') { 117 | sh "helm version" 118 | sh "sed -i \"s/lusyoe\\/springboot-devops-demo/${params.REGISTRY_URL}\\/lusyoe\\/springboot-devops-demo:${shortGitCommit}/g\" charts/values.yaml" 119 | //sh "helm upgrade --install springboot-devops-demo charts/" 120 | } 121 | } 122 | //container('jnlp') { 123 | //stage("Archive") { 124 | //archiveArtifacts artifacts: 'build/archive/*.*', fingerprint: true, allowEmptyArchive: true 125 | //} 126 | //} 127 | 128 | // catch(Exception e) { 129 | // currentBuild.result = "FAILURE" 130 | // }finally { 131 | // // 获取执行状态 132 | // def currResult = currentBuild.result ?: 'SUCCESS' 133 | // // 判断执行任务状态,根据不同状态发送邮件 134 | // stage('email'){ 135 | // if (currResult == 'SUCCESS') { 136 | // echo "发送成功邮件" 137 | // emailext(subject: '任务执行成功',to: '3*****7@qq.com',body: '''任务已经成功构建完成...''') 138 | // }else { 139 | // echo "发送失败邮件" 140 | // emailext(subject: '任务执行失败',to: '3*****7@qq.com',body: '''任务执行失败构建失败...''') 141 | // } 142 | // } 143 | // } 144 | } 145 | 146 | } 147 | 148 | // vim: ft=groovy 149 | 150 | -------------------------------------------------------------------------------- /jenkins/Jenkinsfile-charts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | def projectProperties = [ 4 | [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '5']], 5 | parameters([ 6 | string(name: 'DOCKER_USER', defaultValue: '', description: 'docker用户名'), 7 | string(name: 'DOCKER_PASSWORD', defaultValue: '', description: 'docker用户密码'), 8 | string(name: 'REGISTRY_URL', defaultValue: 'docker.io', description: 'docker仓库地址') 9 | ]) 10 | ] 11 | 12 | properties(projectProperties) 13 | 14 | def label = "mypod-${UUID.randomUUID().toString()}" 15 | 16 | podTemplate(label: label, cloud: 'kubernetes', containers: [ 17 | containerTemplate(name: 'maven', image: 'maven:3.6.0-jdk-8', command: 'cat', ttyEnabled: true), 18 | containerTemplate(name: 'docker', image: 'docker', command: 'cat', ttyEnabled: true), 19 | containerTemplate(name: 'helm', image: 'lachlanevenson/k8s-helm:v2.9.1', command: 'cat', ttyEnabled: true, envVars: [ 20 | envVar(key: 'KUBECONFIG', value: '/root/.kube/config')]) 21 | ], 22 | volumes: [ 23 | hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'), 24 | hostPathVolume(hostPath: '/root/.kube', mountPath: '/root/.kube'), 25 | hostPathVolume(hostPath: '/root/.m2', mountPath: '/root/.m2') 26 | ], 27 | annotations: [ 28 | podAnnotation(key: "sidecar.istio.io/inject", value: "false") 29 | ] 30 | 31 | ) { 32 | 33 | node(label) { 34 | 35 | def gitCommit 36 | def shortGitCommit 37 | def previousGitCommit 38 | 39 | container('maven') { 40 | 41 | stage('checkout') { 42 | checkout scm 43 | 44 | sh 'printenv' 45 | 46 | gitCommit = sh(script: "git rev-parse HEAD", returnStdout: true).trim() 47 | shortGitCommit = "${gitCommit[0..10]}" 48 | previousGitCommit = sh(script: "git rev-parse ${gitCommit}~", returnStdout: true) 49 | 50 | echo "gitCommit = ${gitCommit}" 51 | echo "shortGitCommit = ${shortGitCommit}" 52 | echo "previousGitCommit = ${previousGitCommit}" 53 | } 54 | 55 | stage('pacakge') { 56 | 57 | sh 'mvn clean package -Dmaven.test.skip=true -s ./settings.xml' 58 | } 59 | } 60 | 61 | container('docker') { 62 | 63 | stage('docker-login') { 64 | //REGISTRY_URL私有仓库地址,也可使用官方地址:docker.io 65 | sh "docker login -u ${params.DOCKER_USER} -p ${params.DOCKER_PASSWORD} ${params.REGISTRY_URL}" 66 | } 67 | 68 | stage('docker-build') { 69 | sh "docker build . -t ${params.REGISTRY_URL}/lusyoe/springboot-devops-demo:${shortGitCommit}" 70 | } 71 | 72 | stage('docker-push') { 73 | sh "docker push ${params.REGISTRY_URL}/lusyoe/springboot-devops-demo:${shortGitCommit}" 74 | } 75 | 76 | stage('docker-remove') { 77 | sh "docker rmi ${params.REGISTRY_URL}/lusyoe/springboot-devops-demo:${shortGitCommit}" 78 | } 79 | } 80 | 81 | 82 | container('helm') { 83 | stage('helm deploy') { 84 | sh "sed -i \"s/lusyoe\\/springboot-devops-demo/${params.REGISTRY_URL}\\/lusyoe\\/springboot-devops-demo:${shortGitCommit}/g\" charts/values.yaml" 85 | sh "helm upgrade --install springboot-devops-demo charts/" 86 | } 87 | } 88 | 89 | } 90 | } 91 | 92 | // vim: ft=groovy 93 | -------------------------------------------------------------------------------- /jenkins/Jenkinsfile-old: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | def projectProperties = [ 4 | [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '5']], 5 | parameters([ 6 | string(name: 'DOCKER_USER', defaultValue: '', description: 'docker用户名'), 7 | string(name: 'DOCKER_PASSWORD', defaultValue: '', description: 'docker用户密码'), 8 | string(name: 'REGISTRY_URL', defaultValue: 'docker.io', description: 'docker仓库地址') 9 | ]) 10 | ] 11 | 12 | properties(projectProperties) 13 | 14 | def label = "mypod-${UUID.randomUUID().toString()}" 15 | 16 | podTemplate(label: label, cloud: 'kubernetes', containers: [ 17 | containerTemplate(name: 'maven', image: 'maven:3.6.0-jdk-8', command: 'cat', ttyEnabled: true), 18 | containerTemplate(name: 'docker', image: 'docker', command: 'cat', ttyEnabled: true), 19 | containerTemplate(name: 'kubectl', image: 'lachlanevenson/k8s-kubectl:v1.10.2', command: 'cat', ttyEnabled: true) 20 | ], 21 | volumes: [ 22 | hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'), 23 | hostPathVolume(hostPath: '/root/.kube', mountPath: '/root/.kube'), 24 | hostPathVolume(hostPath: '/root/.m2', mountPath: '/root/.m2') 25 | ], 26 | annotations: [ 27 | podAnnotation(key: "sidecar.istio.io/inject", value: "false") 28 | ] 29 | 30 | ) { 31 | 32 | node(label) { 33 | 34 | def gitCommit 35 | def shortGitCommit 36 | def previousGitCommit 37 | 38 | container('maven') { 39 | 40 | stage('checkout') { 41 | checkout scm 42 | 43 | sh 'printenv' 44 | 45 | gitCommit = sh(script: "git rev-parse HEAD", returnStdout: true).trim() 46 | shortGitCommit = "${gitCommit[0..10]}" 47 | previousGitCommit = sh(script: "git rev-parse ${gitCommit}~", returnStdout: true) 48 | 49 | echo "gitCommit = ${gitCommit}" 50 | echo "shortGitCommit = ${shortGitCommit}" 51 | echo "previousGitCommit = ${previousGitCommit}" 52 | } 53 | 54 | stage('pacakge') { 55 | 56 | sh 'mvn clean package -Dmaven.test.skip=true -s ./settings.xml' 57 | } 58 | } 59 | 60 | container('docker') { 61 | 62 | stage('docker-login') { 63 | //REGISTRY_URL私有仓库地址,也可使用官方地址:docker.io 64 | sh "docker login -u ${params.DOCKER_USER} -p ${params.DOCKER_PASSWORD} ${params.REGISTRY_URL}" 65 | } 66 | 67 | stage('docker-build') { 68 | sh "docker build . -t ${params.REGISTRY_URL}/lusyoe/springboot-devops-demo:${shortGitCommit}" 69 | } 70 | 71 | stage('docker-push') { 72 | sh "docker push ${params.REGISTRY_URL}/lusyoe/springboot-devops-demo:${shortGitCommit}" 73 | } 74 | 75 | stage('docker-remove') { 76 | sh "docker rmi ${params.REGISTRY_URL}/lusyoe/springboot-devops-demo:${shortGitCommit}" 77 | } 78 | 79 | } 80 | 81 | 82 | container('kubectl') { 83 | stage('k8s deploy') { 84 | sh "sed -i \"s/lusyoe\\/springboot-devops-demo/${params.REGISTRY_URL}\\/lusyoe\\/springboot-devops-demo:${shortGitCommit}/g\" springboot-devops-demo.yaml" 85 | sh "kubectl --kubeconfig=/root/.kube/config apply -f springboot-devops-demo.yaml" 86 | } 87 | } 88 | 89 | } 90 | } 91 | 92 | // vim: ft=groovy 93 | -------------------------------------------------------------------------------- /jenkins/admin-rbac.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1beta1 3 | metadata: 4 | name: admin 5 | annotations: 6 | rbac.authorization.kubernetes.io/autoupdate: "true" 7 | roleRef: 8 | kind: ClusterRole 9 | name: cluster-admin 10 | apiGroup: rbac.authorization.k8s.io 11 | subjects: 12 | - kind: ServiceAccount 13 | name: admin 14 | namespace: jenkins 15 | --- 16 | apiVersion: v1 17 | kind: ServiceAccount 18 | metadata: 19 | name: admin 20 | namespace: jenkins 21 | labels: 22 | kubernetes.io/cluster-service: "true" 23 | addonmanager.kubernetes.io/mode: Reconcile 24 | -------------------------------------------------------------------------------- /kaniko/Dockerfile-package: -------------------------------------------------------------------------------- 1 | FROM maven:3.5.0-jdk-8-alpine 2 | 3 | RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 4 | RUN echo 'Asia/Shanghai' >/etc/timezone 5 | 6 | WORKDIR /project 7 | ADD . /project 8 | 9 | #RUN mvn package -Dmaven.test.skip=true 10 | RUN mvn -B clean package -DskipTests 11 | CMD ["mvn"] 12 | 13 | # docker build -t hbstarjason/springboot-devops-demo:jar -f Dockerfile-package . 14 | # docker run hbstarjason/springboot-devops-demo:jar tail -f -------------------------------------------------------------------------------- /kaniko/README.md: -------------------------------------------------------------------------------- 1 | ```bash 2 | $ export GHUSER="hbstarjason" 3 | $ export GHREPO="springboot-devops-demo" 4 | 5 | $ export DOCKERSERVER="https://index.docker.io/v1/" 6 | $ export DOCKERREPO="hbstarjason" 7 | $ export DOCKERPASS="XXXXX" 8 | $ export DOCKEREMAIL="XXXXXX" 9 | 10 | $ kubectl create secret docker-registry hbstarjason \ 11 | --docker-server=${DOCKERSERVER} \ 12 | --docker-username=${DOCKERREPO} \ 13 | --docker-password=${DOCKERPASS} \ 14 | --docker-email=${DOCKEREMAIL} 15 | 16 | $ git clone https://github.com/hbstarjason/springboot-devops-demo && \ 17 | cd springboot-devops-demo/kaniko 18 | 19 | $ kubectl apply -f build.yaml 20 | job.batch/kaniko created 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /kaniko/build.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: kaniko 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name: kaniko 10 | #image: gcr.io/kaniko-project/executor:latest 11 | image: hbstarjason/executor:v0.24.0 12 | args: ["--dockerfile=kaniko/Dockerfile-package", 13 | "--context=git://github.com/hbstarjason/springboot-devops-demo.git#refs/heads/master", 14 | "--destination=hbstarjason/springboot-devops-demo:jar"] 15 | volumeMounts: 16 | - name: kaniko-secret 17 | mountPath: "/kaniko/.docker" 18 | restartPolicy: Never 19 | volumes: 20 | - name: kaniko-secret 21 | secret: 22 | secretName: hbstarjason 23 | items: 24 | - key: .dockerconfigjson 25 | path: config.json 26 | -------------------------------------------------------------------------------- /local-skaffold.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: springboot-devops-demo-local 5 | spec: 6 | containers: 7 | - name: springboot-devops-demo-local 8 | image: hbstarjason/springboot-devops-demo -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /okteto-pipeline.yml: -------------------------------------------------------------------------------- 1 | deploy: 2 | #- mvn -B clean package -DskipTests 3 | #- okteto build -t hbstarjason/springboot-devops-demo 4 | #- skaffold dev 5 | - kubectl apply -f springboot-devops-demo-okteto.yaml 6 | -------------------------------------------------------------------------------- /pics/config_jenkins_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hbstarjason/springboot-devops-demo/e0deb381be792ed97a84d88c91e9e592bdf75107/pics/config_jenkins_pipeline.png -------------------------------------------------------------------------------- /pics/create_jenkins_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hbstarjason/springboot-devops-demo/e0deb381be792ed97a84d88c91e9e592bdf75107/pics/create_jenkins_pipeline.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | k8s 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | k8s 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.1.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | 40 | 41 | ${project.artifactId} 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-maven-plugin 47 | 48 | 49 | 50 | org.codehaus.mojo 51 | cobertura-maven-plugin 52 | 2.7 53 | 54 | 55 | html 56 | xml 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | ~/.m2 10 | 11 | 12 | 13 | nexus 14 | aliyun maven 15 | http://maven.aliyun.com/nexus/content/groups/public/ 16 | * 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /skaffold.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: skaffold/v2beta5 2 | kind: Config 3 | build: 4 | artifacts: 5 | - image: hbstarjason/springboot-devops-demo 6 | deploy: 7 | kubectl: 8 | manifests: 9 | - local-skaffold.yaml 10 | 11 | -------------------------------------------------------------------------------- /sonarqube/docker-compose-sonarqube.yml: -------------------------------------------------------------------------------- 1 | 2 | ### wget https://github.com/docker/compose/releases/download/1.24.0/docker-compose-Linux-x86_64 && \mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose && docker-compose --version 3 | ### sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose && docker-compose --version 4 | 5 | ### docker-compose -f docker-compose-sonarqube.yml up -d 6 | 7 | version: "2" 8 | 9 | services: 10 | sonarqube: 11 | image: sonarqube 12 | ports: 13 | - "9000:9000" 14 | networks: 15 | - sonarnet 16 | environment: 17 | - SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar 18 | volumes: 19 | - sonarqube_conf:/opt/sonarqube/conf 20 | - sonarqube_data:/opt/sonarqube/data 21 | - sonarqube_extensions:/opt/sonarqube/extensions 22 | - sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins 23 | 24 | db: 25 | image: postgres 26 | networks: 27 | - sonarnet 28 | environment: 29 | - POSTGRES_USER=sonar 30 | - POSTGRES_PASSWORD=sonar 31 | volumes: 32 | - postgresql:/var/lib/postgresql 33 | - postgresql_data:/var/lib/postgresql/data 34 | 35 | networks: 36 | sonarnet: 37 | driver: bridge 38 | 39 | volumes: 40 | sonarqube_conf: 41 | sonarqube_data: 42 | sonarqube_extensions: 43 | sonarqube_bundled-plugins: 44 | postgresql: 45 | postgresql_data: -------------------------------------------------------------------------------- /spinnaker/spinnaker-manifest.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: trigger-demo-github 5 | --- 6 | apiVersion: apps/v1 7 | kind: Deployment 8 | metadata: 9 | labels: 10 | app: springboot-devops-demo 11 | tier: backend 12 | name: springboot-devops-demo 13 | namespace: trigger-demo-github 14 | spec: 15 | replicas: 2 16 | selector: 17 | matchLabels: 18 | app: springboot-devops-demo 19 | tier: backend 20 | template: 21 | metadata: 22 | labels: 23 | app: springboot-devops-demo 24 | tier: backend 25 | spec: 26 | containers: 27 | - image: 'hbstarjason/springboot-devops-demo:latest' 28 | livenessProbe: 29 | httpGet: 30 | path: / 31 | port: 8080 32 | initialDelaySeconds: 15 33 | name: springboot-devops-demo 34 | ports: 35 | - containerPort: 8080 36 | readinessProbe: 37 | httpGet: 38 | path: / 39 | port: 8080 40 | initialDelaySeconds: 10 41 | resources: 42 | requests: 43 | cpu: 100m 44 | memory: 100Mi 45 | --- 46 | apiVersion: v1 47 | kind: Service 48 | metadata: 49 | labels: 50 | app: springboot-devops-demo 51 | tier: backend 52 | name: springboot-devops-demo 53 | namespace: trigger-demo-github 54 | spec: 55 | ports: 56 | - name: k8s-backend 57 | port: 8080 58 | selector: 59 | app: springboot-devops-demo 60 | tier: backend 61 | -------------------------------------------------------------------------------- /spinnaker/trigger-demo-dockerhub.json: -------------------------------------------------------------------------------- 1 | { 2 | "keepWaitingPipelines": false, 3 | "limitConcurrent": true, 4 | "stages": [ 5 | { 6 | "account": "k8s-spin", 7 | "cloudProvider": "kubernetes", 8 | "manifestArtifactAccount": "embedded-artifact", 9 | "manifests": [ 10 | { 11 | "apiVersion": "v1", 12 | "kind": "Namespace", 13 | "metadata": { 14 | "name": "trigger-demo-dockerhub" 15 | } 16 | }, 17 | { 18 | "apiVersion": "apps/v1", 19 | "kind": "Deployment", 20 | "metadata": { 21 | "labels": { 22 | "app": "springboot-devops-demo", 23 | "tier": "backend" 24 | }, 25 | "name": "springboot-devops-demo", 26 | "namespace": "trigger-demo-dockerhub" 27 | }, 28 | "spec": { 29 | "replicas": 1, 30 | "selector": { 31 | "matchLabels": { 32 | "app": "springboot-devops-demo", 33 | "tier": "backend" 34 | } 35 | }, 36 | "template": { 37 | "metadata": { 38 | "labels": { 39 | "app": "springboot-devops-demo", 40 | "tier": "backend" 41 | } 42 | }, 43 | "spec": { 44 | "containers": [ 45 | { 46 | "image": "hbstarjason/springboot-devops-demo:${trigger.tag}", 47 | "livenessProbe": { 48 | "httpGet": { 49 | "path": "/", 50 | "port": 8080 51 | }, 52 | "initialDelaySeconds": 15 53 | }, 54 | "name": "springboot-devops-demo", 55 | "ports": [ 56 | { 57 | "containerPort": 8080 58 | } 59 | ], 60 | "readinessProbe": { 61 | "httpGet": { 62 | "path": "/", 63 | "port": 8080 64 | }, 65 | "initialDelaySeconds": 10 66 | }, 67 | "resources": { 68 | "requests": { 69 | "cpu": "100m", 70 | "memory": "100Mi" 71 | } 72 | } 73 | } 74 | ] 75 | } 76 | } 77 | } 78 | }, 79 | { 80 | "apiVersion": "v1", 81 | "kind": "Service", 82 | "metadata": { 83 | "labels": { 84 | "app": "springboot-devops-demo", 85 | "tier": "backend" 86 | }, 87 | "name": "springboot-devops-demo", 88 | "namespace": "trigger-demo-dockerhub" 89 | }, 90 | "spec": { 91 | "ports": [ 92 | { 93 | "name": "k8s-backend", 94 | "port": 8080 95 | } 96 | ], 97 | "selector": { 98 | "app": "springboot-devops-demo", 99 | "tier": "backend" 100 | } 101 | } 102 | } 103 | ], 104 | "moniker": { 105 | "app": "triggerdemo" 106 | }, 107 | "name": "Deploy All", 108 | "refId": "1", 109 | "relationships": { 110 | "loadBalancers": [], 111 | "securityGroups": [] 112 | }, 113 | "requisiteStageRefIds": [], 114 | "source": "text", 115 | "type": "deployManifest" 116 | } 117 | ], 118 | "triggers": [ 119 | { 120 | "account": "my-docker-registry", 121 | "enabled": true, 122 | "job": "springboot-demo", 123 | "master": "my-jenkins-master", 124 | "organization": "hbstarjason", 125 | "registry": "index.docker.io", 126 | "repository": "hbstarjason/springboot-devops-demo", 127 | "tag": "", 128 | "type": "docker" 129 | } 130 | ] 131 | } 132 | -------------------------------------------------------------------------------- /springboot-devops-demo-argocd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: springboot-devops-demo 5 | namespace: springboot-devops-demo 6 | spec: 7 | project: default 8 | source: 9 | repoURL: https://github.com/hbstarjason/springboot-devops-demo.git 10 | targetRevision: master 11 | path: argocd 12 | destination: 13 | server: https://kubernetes.default.svc 14 | namespace: springboot-devops-demo 15 | syncPolicy: 16 | automated: 17 | prune: true -------------------------------------------------------------------------------- /springboot-devops-demo-okteto.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: springboot-devops-demo 5 | labels: 6 | app: springboot-devops-demo 7 | tier: backend 8 | spec: 9 | replicas: 3 10 | selector: 11 | matchLabels: 12 | app: springboot-devops-demo 13 | tier: backend 14 | template: 15 | metadata: 16 | labels: 17 | app: springboot-devops-demo 18 | tier: backend 19 | spec: 20 | containers: 21 | - name: springboot-devops-demo 22 | image: hbstarjason/springboot-devops-demo 23 | resources: 24 | requests: 25 | cpu: 100m 26 | memory: 100Mi 27 | ports: 28 | - containerPort: 8080 29 | readinessProbe: 30 | httpGet: 31 | path: / 32 | port: 8080 33 | initialDelaySeconds: 10 34 | livenessProbe: 35 | httpGet: 36 | path: / 37 | port: 8080 38 | initialDelaySeconds: 15 39 | 40 | --- 41 | apiVersion: v1 42 | kind: Service 43 | metadata: 44 | name: springboot-devops-demo 45 | labels: 46 | app: springboot-devops-demo 47 | tier: backend 48 | spec: 49 | selector: 50 | app: springboot-devops-demo 51 | tier: backend 52 | ports: 53 | - port: 8080 54 | name: k8s-backend 55 | type: LoadBalancer 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /springboot-devops-demo-sidecar.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | #namespace: springboot-devops-demo 5 | name: springboot-devops-demo 6 | labels: 7 | app: springboot-devops-demo 8 | tier: backend 9 | spec: 10 | replicas: 2 11 | selector: 12 | matchLabels: 13 | app: springboot-devops-demo 14 | tier: backend 15 | template: 16 | metadata: 17 | labels: 18 | app: springboot-devops-demo 19 | tier: backend 20 | spec: 21 | # refs: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-initialization/ 22 | initContainers: 23 | - name: sidecar-jar 24 | image: hbstarjason/springboot-devops-demo:jar 25 | imagePullPolicy: IfNotPresent 26 | #command: ["cp", "-r", "/project/target/", "/opt"] 27 | command: ["cp", "/project/target/k8s.jar", "/opt"] 28 | volumeMounts: 29 | - name: sidecar 30 | mountPath: /opt 31 | containers: 32 | - name: runtime 33 | image: openjdk:8 34 | resources: 35 | requests: 36 | memory: "200Mi" 37 | cpu: "200m" 38 | limits: 39 | memory: "200Mi" 40 | cpu: "200m" 41 | ports: 42 | - containerPort: 8080 43 | command: ["bash", "-c", "java -jar /opt/k8s.jar -Djava.security.egd=file:/dev/./urandom"] 44 | #command: ["bash", "-c", "java ${JAVA_OPTS} -jar /opt/app.jar -Djava.security.egd=file:/dev/./urandom"] 45 | #env: 46 | # - name: JAVA_OPTS 47 | # value: "-javaagent:/sidecar/sidecar/skywalking/agent/skywalking-agent.jar" 48 | volumeMounts: 49 | - name: sidecar 50 | mountPath: /opt 51 | volumes: 52 | - name: sidecar 53 | emptyDir: {} 54 | 55 | --- 56 | apiVersion: v1 57 | kind: Service 58 | metadata: 59 | name: springboot-devops-demo 60 | labels: 61 | app: springboot-devops-demo 62 | tier: backend 63 | spec: 64 | selector: 65 | app: springboot-devops-demo 66 | tier: backend 67 | ports: 68 | - port: 8080 69 | name: k8s-backend 70 | #type: LoadBalancer 71 | type: NodePort -------------------------------------------------------------------------------- /springboot-devops-demo.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: springboot-devops-demo 5 | labels: 6 | app: springboot-devops-demo 7 | tier: backend 8 | spec: 9 | replicas: 3 10 | selector: 11 | matchLabels: 12 | app: springboot-devops-demo 13 | tier: backend 14 | template: 15 | metadata: 16 | labels: 17 | app: springboot-devops-demo 18 | tier: backend 19 | spec: 20 | containers: 21 | - name: springboot-devops-demo 22 | image: hbstarjason/springboot-devops-demo 23 | resources: 24 | requests: 25 | cpu: 100m 26 | memory: 100Mi 27 | ports: 28 | - containerPort: 8080 29 | readinessProbe: 30 | httpGet: 31 | path: / 32 | port: 8080 33 | initialDelaySeconds: 10 34 | livenessProbe: 35 | httpGet: 36 | path: / 37 | port: 8080 38 | initialDelaySeconds: 15 39 | 40 | --- 41 | apiVersion: v1 42 | kind: Service 43 | metadata: 44 | name: springboot-devops-demo 45 | labels: 46 | app: springboot-devops-demo 47 | tier: backend 48 | spec: 49 | selector: 50 | app: springboot-devops-demo 51 | tier: backend 52 | ports: 53 | - port: 8080 54 | name: k8s-backend 55 | 56 | --- 57 | apiVersion: extensions/v1beta1 58 | kind: Ingress 59 | metadata: 60 | name: springboot-devops-demo 61 | spec: 62 | rules: 63 | - host: springboot-devops-demo.com 64 | http: 65 | paths: 66 | - backend: 67 | serviceName: springboot-devops-demo 68 | servicePort: k8s-backend 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/example/k8s/K8sApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.k8s; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class K8sApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(K8sApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/example/k8s/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.example.k8s.controller; 2 | 3 | 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | public class HelloController { 9 | 10 | @GetMapping("/") 11 | public String sayHello() { 12 | return "Hello, springboot-devops-demo!"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hbstarjason/springboot-devops-demo/e0deb381be792ed97a84d88c91e9e592bdf75107/src/main/resources/application.properties -------------------------------------------------------------------------------- /src/test/java/com/example/k8s/K8sApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.k8s; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class K8sApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /test/scripts/clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | 5 | set -e 6 | 7 | CONTAINER_NAME=$1 8 | [[ "${CONTAINER_NAME}" == "" ]] && exit 1 9 | 10 | docker ps | grep -e ${CONTAINER_NAME} | awk '{print $1}' | xargs docker stop 11 | docker ps -a | grep -e ${CONTAINER_NAME} | awk '{print $1}' | xargs docker rm 12 | -------------------------------------------------------------------------------- /test/scripts/minikube.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | K8S_VER=$2 6 | if [[ "${K8S_VER}" == "" ]]; then 7 | K8S_VER="k8s-v1.15.4" 8 | fi 9 | 10 | function waitMinikube() { 11 | set +e 12 | kubectl cluster-info 13 | # This for loop waits until kubectl can access the api server that Minikube has created. 14 | for _ in {1..24}; do # Timeout for 240 seconds. 15 | kubectl get po --all-namespaces 16 | if [ $? -ne 1 ]; then 17 | break 18 | fi 19 | sleep 10 20 | done 21 | if ! kubectl get all --all-namespaces; then 22 | echo "Kubernetes failed to start" 23 | ps ax 24 | netstat -an 25 | docker images 26 | cat /var/lib/localkube/localkube.err 27 | printf '\n\n\n' 28 | kubectl cluster-info dump 29 | exit 1 30 | fi 31 | 32 | echo "Minikube is running" 33 | 34 | for _ in {1..6}; do # Timeout for 60 seconds. 35 | echo "$(sudo -E minikube ip) minikube.local" | sudo tee -a /etc/hosts 36 | ip=$(cat /etc/hosts | grep minikube.local | cut -d' ' -f1 | xargs) 37 | if [ -n "$ip" ]; then 38 | break 39 | fi 40 | sleep 10 41 | done 42 | 43 | ip=$(cat /etc/hosts | grep minikube.local | cut -d' ' -f1 | xargs) 44 | if [ -n "$ip" ]; then 45 | echo "minikube.local is mapped to $ip" 46 | else 47 | exit 1 48 | fi 49 | } 50 | 51 | # startMinikubeNone starts real kubernetes minikube with none driver. This requires `sudo`. 52 | function startMinikubeNone() { 53 | export MINIKUBE_WANTUPDATENOTIFICATION=false 54 | export MINIKUBE_WANTREPORTERRORPROMPT=false 55 | export MINIKUBE_HOME=$HOME 56 | export CHANGE_MINIKUBE_NONE_USER=true 57 | 58 | # Troubleshoot problem with Docker build on some CircleCI machines. 59 | if [ -f /proc/sys/net/ipv4/ip_forward ]; then 60 | echo "IP forwarding setting: $(cat /proc/sys/net/ipv4/ip_forward)" 61 | echo "My hostname is:" 62 | hostname 63 | echo "My distro is:" 64 | cat /etc/*-release 65 | echo "Contents of /etc/sysctl.d/" 66 | ls -l /etc/sysctl.d/ || true 67 | echo "Contents of /etc/sysctl.conf" 68 | grep ip_forward /etc/sysctl.conf 69 | echo "Config files setting ip_forward" 70 | find /etc/sysctl.d/ -type f -exec grep ip_forward \{\} \; -print 71 | if [ "$(cat /proc/sys/net/ipv4/ip_forward)" -eq 0 ]; then 72 | whoami 73 | echo "Cannot build images without IPv4 forwarding, attempting to turn on forwarding" 74 | sudo sysctl -w net.ipv4.ip_forward=1 75 | if [ "$(cat /proc/sys/net/ipv4/ip_forward)" -eq 0 ]; then 76 | echo "Cannot build images without IPv4 forwarding" 77 | exit 1 78 | fi 79 | fi 80 | fi 81 | 82 | sudo -E minikube config set WantUpdateNotification false 83 | sudo -E minikube config set WantReportErrorPrompt false 84 | sudo -E minikube start --kubernetes-version=${K8S_VER#k8s-} --driver=none 85 | } 86 | 87 | function stopMinikube() { 88 | sudo minikube stop 89 | } 90 | 91 | case "$1" in 92 | start) startMinikubeNone ;; 93 | stop) stopMinikube ;; 94 | wait) waitMinikube ;; 95 | esac 96 | -------------------------------------------------------------------------------- /test/scripts/pre.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | 5 | HELMVERSION=$1 6 | if [[ "${HELMVERSION}" == "" ]]; then 7 | HELMVERSION="helm-v3.0.0" 8 | fi 9 | 10 | MINIKUBEVERESION=$2 11 | if [[ "${MINIKUBEVERESION}" == "" ]]; then 12 | MINIKUBEVERESION="minikube-v1.8.0" 13 | fi 14 | 15 | K8SVERSION=$3 16 | if [[ "${K8SVERSION}" == "" ]]; then 17 | K8SVERSION="k8s-v1.15.4" 18 | fi 19 | 20 | # Remove strict host checking. The rest of the file is already populated by the 'add_ssh_keys' step. 21 | mkdir -p ~/.ssh 22 | echo -e "\tStrictHostKeyChecking no" >> ~/.ssh/config 23 | echo -e "\tControlMaster auto" >> ~/.ssh/config 24 | echo -e "\tControlPersist 3600" >> ~/.ssh/config 25 | echo -e "\tControlPath ~/.ssh/%r@%h:%p" >> ~/.ssh/config 26 | 27 | # Create directory for logs. 28 | mkdir -p ~/logs 29 | 30 | # create directory for e2e artifacts. 31 | mkdir -p ~/springboot-devops-demo/test/e2e/artifacts 32 | 33 | curl -sSL https://get.helm.sh/${HELMVERSION}-linux-amd64.tar.gz | \ 34 | sudo tar xz -C /usr/local/bin --strip-components=1 linux-amd64/helm 35 | 36 | sudo mkdir -p /usr/local/bin 37 | curl -sSL "https://storage.googleapis.com/minikube/releases/${MINIKUBEVERESION#minikube-}/minikube-linux-amd64" -o /tmp/minikube 38 | chmod +x /tmp/minikube 39 | sudo mv /tmp/minikube /usr/local/bin/minikube 40 | 41 | curl -sSL "https://storage.googleapis.com/kubernetes-release/release/${K8SVERSION#k8s-}/bin/linux/amd64/kubectl" -o /tmp/kubectl 42 | chmod +x /tmp/kubectl 43 | sudo mv /tmp/kubectl /usr/local/bin/kubectl 44 | 45 | sudo apt-get remove -y --purge man-db 46 | sudo apt-get update 47 | sudo apt-get install -y \ 48 | --no-install-recommends --allow-downgrades --allow-remove-essential --allow-change-held-packages \ 49 | xvfb libgtk-3-0 libnotify4 libgconf-2-4 libnss3 libxss1 libasound2 \ 50 | apt-transport-https \ 51 | ca-certificates \ 52 | curl \ 53 | gnupg-agent \ 54 | software-properties-common \ 55 | openjdk-8-jdk-headless 56 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 57 | sudo apt-key fingerprint 0EBFCD88 58 | sudo add-apt-repository \ 59 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 60 | $(lsb_release -cs) \ 61 | stable" 62 | sudo apt-get update 63 | sudo apt-cache madison docker-ce 64 | sudo apt-get install -y docker-ce=5:19.03.8~3-0~ubuntu-xenial docker-ce-cli=5:19.03.8~3-0~ubuntu-xenial containerd.io 65 | -------------------------------------------------------------------------------- /test/scripts/springboot-devops-demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | set -e 5 | 6 | CURRENT_DIR="$(cd "$(dirname $0)"; pwd)" 7 | 8 | CHART_PATH="$CURRENT_DIR/../chart" 9 | 10 | NAMESPACE="springboot-devops-demo" 11 | 12 | # cd ${CHART_PATH} 13 | 14 | helm repo add stable http://mirror.azure.cn/kubernetes/charts 15 | #helm repo add stable https://kubernetes-charts.storage.googleapis.com/ 16 | helm repo up 17 | 18 | # helm lint ./charts 19 | 20 | sudo sysctl -w vm.max_map_count=262144 21 | sudo sysctl -w vm.drop_caches=1 22 | sudo sysctl -w vm.drop_caches=3 23 | 24 | echo "springboot-devops-demo Deploy" 25 | 26 | kubectl create ns ${NAMESPACE} 27 | helm install springboot-devops-demo ./charts/ -f ./charts/values.yaml -n $NAMESPACE 28 | 29 | helm list -n $NAMESPACE 30 | kubectl get pod -n $NAMESPACE 31 | sleep 60 32 | kubectl get pod -n $NAMESPACE 33 | echo "springboot-devops-demo deployed successfully" 34 | --------------------------------------------------------------------------------