ソースコードのビルド、イメージのプッシュからアプリケーションのデプロイまでの自動化された操作を実装したい場合は、Jenkins を使用してイメージの継続的インテグレーションまたは継続的デリバリー (CI/CD) パイプラインを作成できます。ソースコードを GitLab にコミットすると、Container Registry はそのソースコードを使用して自動的にイメージをビルドします。その後、Container Service for Kubernetes (ACK) がイメージをプルしてアプリケーションをデプロイし、Container Registry が DingTalk グループにイベント通知を送信します。
前提条件
Git、GitLab、および Jenkins がインストールされていること。
説明GitLab には JDK11 ではなく JDK8 がインストールされています。一部の GitLab プラグインは JDK11 では実行できません。
ACR Enterprise Edition インスタンスが作成され、そのインスタンスのインターネットアクセスが有効になっていること。詳細については、「Container Registry Enterprise Edition インスタンスの作成」および「インターネット経由のアクセスを設定する」をご参照ください。
Container Registry Enterprise Edition の Advanced Edition インスタンスと同じリージョンに存在する ACK クラスターが作成されていること。詳細については、「ACK マネージドクラスターの作成」をご参照ください。
DingTalk チャットボットが作成されていること。DingTalk チャットボットの Webhook URL とシークレットトークンが記録されていること。詳細については、「ステップ 1: DingTalk チャットボットを作成する」をご参照ください。
Container Registry のパイプライン機能を使用するには、インスタンスを Advanced Edition にアップグレードする必要があります。詳細については、「課金ルール」をご参照ください。
Jenkins を使用してイメージの CI パイプラインを作成する
ソースコードを GitLab にコミットすると、Container Registry はそのソースコードを使用して自動的にイメージをビルドします。イメージをスキャンした後、Container Registry は自動的に DingTalk グループにイベント通知を送信します。
GitLab でプロジェクトを作成します。
GitLab にログインします。
GitLab コンソールの上部のナビゲーションバーで、 を選択します。
[Your Projects] ページで、右上隅にある [New Project] をクリックし、次に [Create Blank Project] をクリックします。
[Create Blank Project] ページで、[Project Name]、[Project URL]、[Project Slug] パラメーターを設定し、[Visibility Level] を [Private] に設定してから、[Create Project] をクリックします。

オンプレミスのコンピューターに Dockerfile、pom.xml、DemoApplication.java、および HelloController.java ファイルを作成します。
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/> <!-- リポジトリから親を検索 --> </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()); } }
次のコマンドを実行して、ビルドファイルを GitLab にアップロードします。
cd java-web # ビルドファイルが存在するディレクトリに移動します。 git remote set-url origin http://8.218.20*.***/shoppingmall/java-web.git git push origin master * [new branch] master -> master
Jenkins でイメージをビルドするためのパイプラインを作成します。
Jenkins で GitLab の Secure Shell (SSH) キーペアを設定します。
Jenkins にログインします。
Jenkins ダッシュボードの左側のナビゲーションウィンドウで、[Manage Jenkins] をクリックします。
[Security] セクションで、[Manage Credentials] をクリックします。
[Stores Scoped To Jenkins] セクションで、[Store] 列の [Jenkins] をクリックし、次に [Global Credentials] をクリックします。
左側のナビゲーションウィンドウで、[Add Credentials] をクリックします。
Kind パラメーターを [SSH Username With Private Key] に設定し、[Description] および [Username] パラメーターに値を入力し、[Enter Directly] を選択してから [OK] をクリックします。
[Global Credentials] ページで、認証情報の ID が自動的に生成されます。ID を記録します。
パイプラインを作成します。
Jenkins ダッシュボードの左側のナビゲーションウィンドウで、[New Item] をクリックします。
パイプラインの名前を入力し、[Pipeline] を選択してから [OK] をクリックします。
[Build Triggers] タブをクリックし、[Build When A Change Is Pushed To GitLab] を選択し、次に [Push Events] を選択します。
[Build When A Change Is Pushed To GitLab] の右側にある Webhook URL を記録します。
[Advanced] をクリックし、[Secret Token] の右下隅にある [Generate] をクリックします。
Jenkins によって生成されたシークレットトークンを記録します。
[Pipeline] タブをクリックし、次のテンプレートのパラメーターの値を実際の値に置き換えます。変更した内容をコードエディタにコピーし、[Save] をクリックします。
def git_auth_id = "6d5a2c06-f0a7-43c8-9b79-37b8c266****" # 認証情報の ID。 def git_branch_name = "master" # ブランチの名前。 def git_url = "git@172.16.1*.***:shoppingmall/java-web.git" # GitLab リポジトリのアドレス。 def acr_url = "s*****-devsecops-registry.cn-hongkong.cr.aliyuncs.com" # イメージリポジトリのエンドポイント。 def acr_username = "acr_test_*****@test.aliyunid.com" # コンテナイメージのユーザー名。 def acr_password = "HelloWorld2021" # コンテナイメージのパスワード。 def acr_namespace = "ns" # 名前空間の名前。 def acr_repo_name = "test" # イメージリポジトリの名前。 def tag_version = "0.0.1" # コンテナイメージのタグ。 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}" } }
Webhook URL を GitLab に追加します。
GitLab にログインします。
[Projects] ページで、作成したプロジェクトの名前をクリックします。
左側のナビゲーションウィンドウで、 を選択します。Webhook URL とシークレットトークンを入力し、[Enable SSL Verification] をクリアしてから、[Add Webhooks] をクリックします。
イベント通知ルールを作成します。
Container Registry コンソールにログインします。
上部のナビゲーションバーで、リージョンを選択します。
左側のナビゲーションウィンドウで、[インスタンス] をクリックします。
[インスタンス] ページで、管理する Enterprise Edition インスタンスをクリックします。
インスタンス詳細ページの左側のナビゲーションウィンドウで、 を選択します。
[イベントルール] タブで、[ルールを作成] をクリックします。
ルールを作成ウィザードの [イベント範囲] ステップで、[ルール名] パラメーターに値を入力し、[イベントタイプ] パラメーターを [イメージがスキャンされました] に設定し、[スキャン完了] を選択し、[有効範囲] を [名前空間] に設定し、名前空間の名前として ns を選択してから [次へ] をクリックします。
[イベント通知] ステップで、[通知方法] を [DingTalk] に設定し、DingTalk チャットボットの Webhook URL とシークレットトークンを入力してから、[保存] をクリックします。
イメージビルドをトリガーします。
次のコマンドを実行し、HelloController.java ファイル内のパラメーターの値を実際の値に置き換えます。ファイルを GitLab にコミットして、イメージビルドをトリガーします。
vim java/com/example/demo/HelloController.java # HelloController.java ファイルのパラメーターの値を実際の値に置き換えます。 git add . && git commit -m 'commit' && git push origin # ファイルを GitLab にコミットします。しばらく待ちます。Container Registry Enterprise Edition インスタンスの詳細ページの左側のナビゲーションウィンドウで、 を選択します。表示されたページの右側で、テストリポジトリをクリックします。リポジトリの管理ページの左側のナビゲーションウィンドウで、[タグ] をクリックします。[タグ] ページにイメージが生成されます。
セキュリティスキャンを設定します。
タグページで、イメージの Actions 列にある [セキュリティスキャン] をクリックします。
セキュリティスキャン ページで、[今すぐスキャン] をクリックします。
イメージがスキャンされた後、Container Registry は DingTalk グループに通知を送信します。
Jenkins を使用してイメージの CD パイプラインを作成する
GitLab でソースコードをコミットすると、Container Registry はそのソースコードを使用して自動的にイメージをビルドします。イメージがビルドされると、デリバリーチェーンが自動的にトリガーされます。デリバリーチェーンが実行されると、HTTP リクエストが自動的に Jenkins に送信されます。その後、ACK のデプロイメントがトリガーされ、イメージを再度プルしてアプリケーションをデプロイします。
アプリケーションを作成します。
ACK コンソールにログインします。
ACK コンソールの左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、管理するクラスターを見つけ、クラスターの名前をクリックするか、[アクション] 列の [詳細] をクリックします。クラスターの詳細ページが表示されます。
詳細ページの左側のナビゲーションウィンドウで、 を選択します。
[デプロイメント] ページで、[名前空間] の値を選択し、[YAML から作成] をクリックします。
[作成] ページで、[サンプルテンプレート] ドロップダウンリストから [カスタム] を選択し、次の内容をテンプレートにコピーしてから [作成] をクリックします。
説明ACK と Container Registry でシークレットなしでのイメージのプル機能を有効にしない場合は、Container Registry でインターネット経由のアクセス機能を有効にし、イメージタイプをパブリックに設定する必要があります。詳細については、「インターネット経由のアクセスを設定する」をご参照ください。
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 ---[デプロイメント] ページで、アプリケーションデモの名前をクリックします。[アクセス方法] タブをクリックします。
[アクセス方法] タブで外部エンドポイントを取得します。
ローカルホストに次の内容を入力します。
<The external endpoint> app.demo.example.comブラウザのアドレスバーに app.demo.example.com と入力します。
前の図に示すようなページが表示された場合、アプリケーションはデプロイされています。
アプリケーショントリガーを作成します。
デプロイメントページで、アプリケーションデモの名前をクリックします。
アプリケーションの詳細ページで、[トリガー] タブをクリックします。次に、[トリガーを作成] をクリックします。
[トリガーを作成] ダイアログボックスで、[アクション] を [再デプロイ] に設定し、[OK] をクリックします。
[トリガー] タブで Webhook URL を取得します。
パイプラインを作成します。
Jenkins にログインします。
左側のナビゲーションウィンドウで、[New Item] をクリックします。
パイプラインの名前を入力し、[Pipeline] をクリックします。
[ビルドトリガー] タブをクリックし、[Generic Webhook Trigger] を選択します。
[Generic Webhook Trigger] セクションで、HTTP リクエストの Webhook URL を取得できます。これは
JENKINS_URL/generic-webhook-trigger/invokeです。この例では、汎用 Webhook トークンはhelloworld2021に設定されています。したがって、Webhook URL はJENKINS_URL/generic-webhook-trigger/invoke?token=helloworld2021です。[Pipeline] タブをクリックし、次のテンプレートの汎用 Webhook トークンと Webhook URL を実際の値に置き換えます。変更した内容をコードエディタにコピーし、[保存] をクリックします。
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', # 汎用 Webhook トークン。トークンを実際の値に置き換えます。 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****' # Webhook URL を実際の値に置き換えます。 sh "echo 'done'" } } } }
パイプラインを作成します。詳細については、「デリバリーチェーンの作成」をご参照ください。
イベント通知ルールを作成します。
Container Registry Enterprise Edition インスタンスの管理ページの左側のナビゲーションウィンドウで、 を選択します。
[イベントルール] タブで、[ルールを作成] をクリックします。
ルールを作成ウィザードの [イベント範囲] ステップで、[ルール名] パラメーターに名前を入力し、[イベントタイプ] を [デリバリーチェーンが処理されました] に設定し、[成功] を選択し、[有効範囲] を [名前空間] に設定し、名前空間ドロップダウンリストから ns を選択してから [次へ] をクリックします。
[イベント通知] ステップで、[通知方法] パラメーターを [HTTP] に設定し、ステップ 3 で取得した Webhook URL を入力してから、[保存] をクリックします。
次のコマンドを実行し、HelloController.java ファイル内のパラメーターの値を実際の値に置き換えます。コードを GitLab にコミットして、イメージビルドをトリガーします。
vim java/com/example/demo/HelloController.java # HelloController.java ファイルのパラメーターの値を実際の値に置き換えます。 git add . && git commit -m 'add update' && git push origin # ファイルを GitLab にコミットします。イメージがビルドされると、デリバリーチェーンがトリガーされます。デリバリーチェーンが実行されると、ACK のデプロイメントがトリガーされ、イメージを再度プルしてアプリケーションをデプロイします。
次のコマンドを実行して、アプリケーションが再デプロイされたかどうかを確認します。
curl app.demo.example.comコマンドの出力が変更された場合、アプリケーションは再デプロイされています。