Este tutorial demonstra como criar um fluxo de trabalho totalmente automatizado que compila uma imagem a partir do código-fonte, envia a imagem para um repositório e implanta o aplicativo. Com o Jenkins integrado ao GitLab, Container Registry (ACR) e Container Service for Kubernetes (ACK), você compila imagens automaticamente ao confirmar alterações no código-fonte, implanta aplicativos e envia notificações de eventos para um grupo do DingTalk.
Pré-requisitos
-
Git, GitLab e Jenkins instalados.
NotaO GitLab requer o JDK 8. Alguns plugins não são executados no JDK 11.
Instância do ACR Enterprise Edition criada e com acesso à internet habilitado. Para mais informações, consulte Criar uma instância Enterprise Edition e Configurar acesso à internet.
Cluster ACK criado na mesma região da sua instância do ACR. Para mais informações, consulte Criar um cluster gerenciado ACK.
Chatbot do DingTalk criado, com a URL do webhook e o token secreto registrados. Para mais informações, consulte Etapa 1: Criar um chatbot do DingTalk.
Para usar o recurso de cadeia de entrega do Container Registry (ACR), atualize sua instância para a Advanced Edition. Para mais informações, consulte Faturamento.
CI para imagens com Jenkins
Ao confirmar alterações no código-fonte no GitLab, o Container Registry (ACR) compila a imagem automaticamente. Em seguida, execute uma verificação de segurança na imagem. Após a conclusão da verificação, o sistema envia uma notificação de evento ao 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.

-
Use o conteúdo abaixo para criar os arquivos Dockerfile, pom.xml, DemoApplication.java e HelloController.java no seu computador local.
-
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 o comando a seguir para enviar os arquivos de build ao GitLab.
cd java-web # Go to 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 a imagem.
-
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. Para a chave privada, selecione Enter directly e clique em OK.
Na página Global credentials, o sistema gera automaticamente um ID para a credencial. Salve este ID para uso posterior.
-
Crie um pipeline.
No painel de navegação à esquerda do painel do Jenkins, 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.
À direita de Build when a change is pushed to GitLab, copie a URL do webhook.
-
Clique em Advanced e, em seguida, clique em Generate ao lado de Secret token.
O Jenkins gera um token secreto. Salve este token para uso posterior.
-
Clique na aba Pipeline. No modelo a seguir, substitua os valores de espaço reservado pelas suas próprias informações. Em seguida, copie o conteúdo para a caixa de texto e clique em Save.
def git_auth_id = "6d5a2c06-f0a7-43c8-9b79-37b8c266****" # Credential ID. def git_branch_name = "master" # Branch name. def git_url = "git@172.16.1*.***:shoppingmall/java-web.git" # GitLab repository URL. def acr_url = "s*****-devsecops-registry.cn-hongkong.cr.aliyuncs.com" # Image repository URL. def acr_username = "acr_test_*****@test.aliyunid.com" # Container Registry username. def acr_password = "HelloWorld2021" # Container Registry password. def acr_namespace = "ns" # Namespace. def acr_repo_name = "test" # Image repository name. def tag_version = "0.0.1" # 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 do 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 do webhook e o token secreto. Desmarque a caixa de seleção Enable SSL verification e clique em Add webhooks.
-
Crie uma regra de notificação de eventos.
Acesse o 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 o Rule Name. Defina Event Type como The image is scanned. e selecione Scanned.. Defina Effective Scope como Namespaces, selecione o namespace
nse clique em Next.Na etapa Event Notification, defina Notification Method como DingTalk. Insira a URL do webhook e o token secreto do seu chatbot do DingTalk e clique em Save.
-
Acione a compilação da imagem.
Execute o comando a seguir para modificar o arquivo
HelloController.javae confirmá-lo no GitLab. Essa ação aciona a compilação da imagem.vim java/com/example/demo/HelloController.java # Modify the HelloController.java file locally based on your needs. git add . && git commit -m 'commit' && git push origin # Commit the file to GitLab.Aguarde alguns instantes. Na página de detalhes da instância Enterprise Edition, escolha no painel de navegação à esquerda. Na página exibida, clique no repositório de destino test. Na página Repository, clique em Tags no painel de navegação à esquerda. Verifique se uma imagem foi gerada na página Tags.
-
Configure uma verificação de segurança.
Na página Security Scan, localize a tag da imagem de destino e clique em Security Scan na coluna Security Scan.
-
Na página Security Scan, clique em Scan.
Após a conclusão da verificação de segurança, você receberá uma notificação no seu grupo do DingTalk.
CD para imagens com Jenkins
Confirmar alterações no código-fonte no GitLab compila automaticamente uma imagem no Container Registry (ACR). A conclusão da compilação aciona uma cadeia de entrega. Após a conclusão da cadeia de entrega, o sistema envia uma solicitação HTTP ao Jenkins. Isso aciona a implantação no ACK para baixar a imagem mais recente e reimplementar o aplicativo.
-
Crie um aplicativo.
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. Copie o código a seguir para o modelo e clique em Create.
NotaSe você não configurar o pull de imagens sem senha, será necessário habilitar o acesso à internet para o Container Registry (ACR) e definir o repositório de imagens como público. Para mais informações, consulte Configurar acesso à 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 no aplicativo
demoe, em seguida, clique na aba Access Method.Na aba Access Method, obtenha o endpoint externo.
-
Adicione a seguinte entrada ao seu arquivo hosts local.
<external endpoint address> app.demo.example.com -
Insira app.demo.example.com na barra de endereços do seu navegador.
A página mostrada acima indica que o aplicativo foi implantado com sucesso. -
Crie um gatilho.
Na página Deployments, clique no aplicativo
demo.Na página de detalhes do aplicativo, 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.
Na seção Generic Webhook Trigger, a URL do gatilho de solicitação HTTP é
JENKINS_URL/generic-webhook-trigger/invoke. Neste tutorial, oGeneric Webhook tokenestá definido comohelloworld2021. Portanto, a URL do webhook éJENKINS_URL/generic-webhook-trigger/invoke?token=helloworld2021. -
Clique na aba Pipeline. No modelo a seguir, substitua o Generic Webhook token e a URL do gatilho de espaço reservado pelos seus valores reais. Copie o conteúdo modificado para a 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', # 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****' # Trigger URL. Replace it with your actual URL. sh "echo 'done'" } } } }
Crie uma cadeia de entrega. Para mais informações, consulte Criar uma cadeia de entrega.
-
Crie uma regra de evento.
Na página de gerenciamento da instância ACR Enterprise Edition, escolha no painel de navegação à esquerda.
Na aba Event Rules, clique em Create Rule.
Na etapa Event Scope, defina o Rule Name. Defina Event Type como The delivery chain is processed. e selecione Success. Defina Effective Scope como Namespaces, selecione o namespace
nse clique em Next.Na etapa Event Notification, defina Notification Method como HTTP. Insira a URL do webhook obtida na Etapa 3 e clique em Save.
-
Execute o comando a seguir para modificar o arquivo
HelloController.javae confirmar o código no GitLab. Essa ação aciona a compilação da imagem.vim java/com/example/demo/HelloController.java # Modify the HelloController.java file locally 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. Quando a cadeia é concluída, a implantação no ACK é acionada para baixar a nova imagem e reimplementar o aplicativo.
-
Execute o comando a seguir para verificar se o aplicativo foi reimplementado.
curl app.demo.example.comSe a saída mudar, o aplicativo foi reimplementado com sucesso.