Este tópico descreve como usar o Jenkins para implementar um pipeline automatizado de ponta a ponta que compila imagens a partir do código-fonte, envia-as para um repositório e implanta aplicações. Ao fazer commit do código-fonte no GitLab, o Container Registry compila automaticamente uma imagem, o Container Service for Kubernetes (ACK) baixa a imagem para implantar a aplicação e o sistema envia uma notificação de evento para um grupo do DingTalk.
Pré-requisitos
-
Git, GitLab e Jenkins instalados.
NotaO GitLab requer o JDK 8. Alguns plugins não funcionam no JDK 11.
Instância do Alibaba Cloud Container Registry (ACR) Enterprise Edition criada e acesso público ativado. Para mais informações, consulte Create an Enterprise Edition instance e Configure access over the Internet.
Cluster do Container Service for Kubernetes (ACK) criado na mesma região da instância do ACR. Para mais informações, consulte Create a managed Kubernetes cluster.
Robô do DingTalk criado, com URL de webhook e token secreto registrados. Para mais informações, consulte Step 1: Create a DingTalk robot.
Para utilizar o recurso de cadeia de entrega do ACR, atualize sua instância para o ACR Advanced Edition. Para mais informações, consulte Billing.
Implementar CI de imagens com o Jenkins
Ao enviar o código-fonte para o GitLab, o Container Registry compila automaticamente uma imagem a partir desse código. Em seguida, execute uma verificação de segurança na imagem. Após a conclusão da verificação, você recebe automaticamente uma notificação de evento em seu grupo do DingTalk.
-
Crie um projeto no GitLab.
Faça login no GitLab.
Na barra de navegação superior, escolha Projects > Your projects.
Na página Projects, clique em New Project no canto superior direito e, em seguida, clique em Create blank project.
-
Na página Create blank project, defina Project name, Project URL e Project slug. Defina Visibility Level como Private e clique em Create project.
Neste exemplo, defina tanto Project name quanto Project slug como
java-web. Para Project URL, selecione shoppingmall como namespace. -
Em sua máquina local, crie os arquivos Dockerfile, pom.xml, DemoApplication.java e HelloController.java com o seguinte conteúdo.
-
Dockerfile
FROM registry.cn-hangzhou.aliyuncs.com/public-toolbox/maven:3.8.3-openjdk-8-aliyun AS build COPY src /home/app/src COPY pom.xml /home/app RUN ["/usr/local/bin/mvn-entrypoint.sh","mvn","-f","/home/app/pom.xml","clean","package","-Dmaven.test.skip=true"] FROM registry.cn-hangzhou.aliyuncs.com/public-toolbox/openjdk:8-jdk-alpine COPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo-0.0.1-SNAPSHOT.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","/usr/local/lib/demo-0.0.1-SNAPSHOT.jar"] -
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.13.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project> -
DemoApplication.java
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.util.TimeZone; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); SpringApplication.run(DemoApplication.class, args); } } -
HelloController.java
package com.example.demo; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.util.Date; @RestController @Slf4j public class HelloController { @RequestMapping({"/hello", "/"}) public String hello(HttpServletRequest request) { return "Hello World at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } }
-
-
Execute os comandos a seguir para enviar os arquivos de compilação ao GitLab.
cd java-web # Enter the directory where the build files are located. git remote set-url origin http://8.218.20*.***/shoppingmall/java-web.git git push origin master * [new branch] master -> master
-
Configure um pipeline no Jenkins para compilar imagens.
-
Configure a chave SSH do GitLab no Jenkins.
Faça login no Jenkins.
No painel de navegação à esquerda, clique em Manage Jenkins.
Na seção Security, clique em Manage Credentials.
Na seção Stores scoped to Jenkins, clique em Jenkins na coluna Store e, em seguida, clique em Global credentials.
No painel de navegação à esquerda, clique em Add Credentials.
-
Defina Kind como SSH Username with private key, insira uma Description e o Username, selecione Enter directly e clique em OK.
Na página Global credentials, o Jenkins gera automaticamente um ID de credencial. Registre esse ID.
-
Crie um pipeline.
No painel de navegação à esquerda, clique em New Item.
Insira um nome para o item, selecione Pipeline e clique em OK.
-
Clique na aba Build Triggers, selecione Build when a change is pushed to GitLab e marque Push Events.
Registre a URL de webhook exibida à direita de Build when a change is pushed to GitLab.
-
Clique em Advanced e, em seguida, clique em Generate no canto inferior direito do campo Secret token.
O Jenkins gera um token secreto. Registre este token.
-
Clique na aba Pipeline, modifique o modelo a seguir com base nas suas informações reais, cole o conteúdo na caixa de texto e clique em Save.
def git_auth_id = "6d5a2c06-f0a7-43c8-9b79-37b8c266****" # The credential ID. def git_branch_name = "master" # The branch name. def git_url = "git@172.16.1*.***:shoppingmall/java-web.git" # The GitLab repository URL. def acr_url = "s*****-devsecops-registry.cn-hongkong.cr.aliyuncs.com" # The image repository URL. def acr_username = "acr_test_*****@test.aliyunid.com" # The Container Registry username. def acr_password = "HelloWorld2021" # The Container Registry password. def acr_namespace = "ns" # The namespace. def acr_repo_name = "test" # The repository name. def tag_version = "0.0.1" # The image tag. node { stage('checkout git repo') { checkout([$class: 'GitSCM', branches: [[name: "*/${git_branch_name}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth_id}", url: "${git_url}"]]]) } stage('build image') { sh "sudo docker build -t java-web:${tag_version} ." sh "sudo docker tag java-web:${tag_version} ${acr_url}/${acr_namespace}/${acr_repo_name}:${tag_version}" } stage('push image') { sh "sudo docker login --username=${acr_username} --password=${acr_password} ${acr_url}" sh "sudo docker push ${acr_url}/${acr_namespace}/${acr_repo_name}:${tag_version}" } }
-
-
Adicione a URL de webhook ao GitLab.
Faça login no GitLab.
Na página Projects, clique no projeto criado.
No painel de navegação à esquerda, escolha Settings > Webhooks. Insira a URL de webhook e o token secreto, desmarque Enable SSL verification e clique em Add webhooks.
-
Crie uma notificação de evento.
Faça login no console do Container Registry.
Na barra de navegação superior, selecione uma região.
No painel de navegação à esquerda, clique em Instances.
Na página Instances, clique na instância Enterprise Edition que deseja gerenciar.
No painel de navegação à esquerda da página de detalhes da instância, escolha .
Na aba Event Rules, clique em Create Rule.
Na etapa Event Scope, defina Rule Name. Defina Event Type como The image is scanned., selecione Scanned., defina Effective Scope como Namespaces, selecione ns como namespace e clique em Next.
Na etapa Event Notification, defina Notification Method como DingTalk, insira a URL de webhook e o token secreto do DingTalk e clique em Save.
-
Acione a compilação da imagem.
Execute os comandos a seguir para modificar o arquivo HelloController.java e enviá-lo ao GitLab. Essa ação aciona a compilação da imagem.
vim java/com/example/demo/HelloController.java # Modify the HelloController.java file on your local machine based on your needs. git add . && git commit -m 'commit' && git push origin # Commit the file to GitLab.Após alguns instantes, na página de detalhes da instância Enterprise Edition, selecione no painel de navegação à esquerda. Na página exibida, clique no repositório de destino
test. No painel de navegação à esquerda da página Repository, clique em Tags. Verifique se uma imagem foi gerada na página Tags. -
Configure uma verificação de segurança.
Na página Tags, localize a tag da imagem de destino e clique em Security Scan na coluna Actions.
-
Na página Security Scan, clique em Scan.
Após a conclusão da verificação de segurança, você receberá uma notificação em seu grupo do DingTalk.
Implementar CD de imagens com o Jenkins
A compilação da imagem aciona automaticamente uma cadeia de entrega. Ao finalizar, a cadeia de entrega envia uma solicitação HTTP ao Jenkins. Essa solicitação faz com que o Deployment no ACK baixe a imagem mais recente e reimplemente a aplicação.
-
Crie uma aplicação.
Faça login no Console de Gerenciamento do Container Service.
No painel de navegação à esquerda, clique em Cluster.
Na página Cluster List, clique no nome do cluster de destino ou clique em Details na coluna Actions.
No painel de navegação à esquerda da página de gerenciamento do cluster, escolha .
-
Na página Deployments, selecione um Namespace e clique em Create from YAML.
-
No painel Create from YAML, defina Sample Template como Custom, cole o conteúdo a seguir no editor de modelos e clique em Create.
NotaSe você não configurar o pull de imagens sem senha, ative o acesso público no Container Registry e defina o repositório como público. Para mais informações, consulte Configure access over the Internet.
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: demo name: demo spec: replicas: 3 minReadySeconds: 5 progressDeadlineSeconds: 60 revisionHistoryLimit: 5 selector: matchLabels: app: demo strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: annotations: prometheus.io/port: "9797" prometheus.io/scrape: "true" creationTimestamp: null labels: app: demo spec: containers: - image: s*****-devsecops-registry.cn-hongkong.cr.aliyuncs.com/ns/test:0.0.1 imagePullPolicy: Always name: demo ports: - containerPort: 8080 name: http protocol: TCP readinessProbe: initialDelaySeconds: 5 tcpSocket: port: 8080 timeoutSeconds: 5 resources: limits: cpu: "2" memory: 512Mi requests: cpu: 100m memory: 64Mi status: {} --- apiVersion: v1 kind: Service metadata: name: demo-svc spec: selector: app: demo ports: - protocol: TCP port: 80 targetPort: 8080 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: demo labels: app: demo spec: rules: - host: app.demo.example.com http: paths: - backend: serviceName: demo-svc servicePort: 80 --- -
Na página Deployments, clique na aplicação de destino, demo, e depois clique na aba Access Method.
Na aba Access Method, obtenha o endpoint externo.
-
Adicione a seguinte entrada ao seu arquivo
hostslocal.<External endpoint address> app.demo.example.com -
Em um navegador, insira app.demo.example.com na barra de endereços.
Hello World 2021 xxx at 2021-12-06 20:51:36A página é exibida, indicando que a aplicação foi implantada com sucesso.
-
Crie um gatilho.
Na página Deployments, clique no nome da aplicação de destino, demo.
Na página de detalhes da aplicação, clique na aba Triggers e, em seguida, clique em Create Trigger.
-
Na caixa de diálogo Create Trigger, defina Action como Redeploy e clique em OK.
Na aba Triggers, obtenha a URL do gatilho.
-
Crie um pipeline.
Faça login no Jenkins.
No painel de navegação à esquerda, clique em New Item.
Insira um nome para o item, selecione Pipeline e clique em OK.
-
Clique na aba Build Triggers e selecione Generic Webhook Trigger.
Em Generic Webhook Trigger, a URL de gatilho de solicitação HTTP segue o formato
JENKINS_URL/generic-webhook-trigger/invoke. Neste tópico,Generic Webhook tokenestá definido comohelloworld2021. Portanto, a URL do webhook éJENKINS_URL/generic-webhook-trigger/invoke?token=helloworld2021. -
Clique na aba Pipeline, modifique o token do Generic Webhook e a URL do gatilho no modelo a seguir com base nas suas informações reais, cole o conteúdo na caixa de texto e clique em Save.
pipeline { agent any triggers { GenericTrigger( genericVariables: [ [key: 'InstanceId', value: '$.data.InstanceId'], [key: 'RepoNamespaceName', value: '$.data.RepoNamespaceName'], [key: 'RepoName', value: '$.data.RepoName'], [key: 'Tag', value: '$.data.Tag'] ], causeString: 'Triggered on $ref', token: 'helloworld2021', # The Generic Webhook token. Replace it with your actual token. tokenCredentialId: '', printContributedVariables: true, printPostContent: true, silentResponse: false, regexpFilterText: '$ref' ) } stages { stage('Some step') { steps { sh "echo 'will print post content'" sh "echo $InstanceId" sh "echo $RepoNamespaceName" sh "echo $RepoName" sh "echo $Tag" sh "echo 'redeploy to ACK or you can deoloy to other platforms use before message'" sh "curl 'https://cs.console.alibabacloud.com/hook/trigger?token=g****' # The trigger URL. Replace it with your actual URL. sh "echo 'done'" } } } }
Crie uma cadeia de entrega. Para mais informações, consulte Create a delivery chain.
-
Crie uma regra de evento.
No painel de navegação à esquerda da página de gerenciamento da instância Enterprise Edition, escolha .
Na aba Event Rules, clique em Create Rule.
Na etapa Event Scope, defina Rule Name. Defina Event Type como The delivery chain is processed., selecione Success, defina Effective Scope como Namespaces, selecione ns como namespace e clique em Next.
Na etapa Event Notification, defina Notification Method como HTTP, insira a URL de webhook obtida na Etapa 3 e clique em Save.
-
Execute os comandos a seguir para modificar o arquivo HelloController.java e enviar o código ao GitLab. Essa ação aciona a compilação da imagem.
vim java/com/example/demo/HelloController.java # Modify the HelloController.java file on your local machine based on your needs. git add . && git commit -m 'add update' && git push origin # Commit the file to GitLab.A compilação da imagem aciona a cadeia de entrega. Após a conclusão da cadeia de entrega, o Deployment no ACK é acionado para baixar a nova imagem e reimplementar a aplicação.
-
Execute o comando a seguir para verificar se a aplicação foi reimplementada.
curl app.demo.example.comA alteração na saída indica que a aplicação foi reimplementada com sucesso.