Red Hat - Open Innovation Labsのブログ - TECH PLAY

TECH PLAY

Red Hat  - Open Innovation Labs

Red Hat - Open Innovation Labs の技術ブログ

全900件

こんにちは。Red Hat ソリューションアーキテクトの清水です。RHEL9から Image Mode for RHEL という新しいオペレーティングシステムのデプロイメント方式が導入されていますが、皆さん触ってみたことはありますか?本ブログ記事では、このImage Mode for RHELを使った仮想マシン(VM)を、Ansibleを使ってデプロイからアップデートを自動化する方法についてご紹介してきたいと思います。 Image Mode for RHEL とは 最初に少しおさらいをしておきましょう。Image Mode for RHELは、元々 bootc というプロジェクトに端を発しており、 RHEL bootc イメージを使って、ブート可能なRHELのコンテナイメージをビルドし、デプロイすることが可能となります。さらに、デプロイしたオペレーティングシステムは、コンテナイメージを通じてアップデートすることも可能です。これにより、既存のコンテナネイティブのツールや手法を使って、アプリケーションから基盤となるオペレーティングシステムまで、全てを一貫してGitOpsで管理し、既存の継続的インテグレーション/継続的デリバリー(CI/CD)に組み込むことも可能となります。 bootc について書き出すとそれだけでシリーズものが出来そうなので、詳細については、 公式ドキュメント を参照してみてください。 Image Mode for RHEL におけるワークフロー 前述の通り、Image Modeを使った場合、通常のアプリケーションコンテナと同様に、オペレーティングシステムをビルド、テスト、デプロイすることができます。こうした運用ワークフローは、最初にシステムとしてデプロイするまでのワークフロー (Day1 オペレーション) とデプロイしたシステムのアップデート (Day2 オペレーション) に大別できます。 デプロイまでのワークフロー (Day1 オペレーション) 先ず、 registry.redhat.io/rhel9/rhel-bootc イメージをベースイメージとして、固有の設定やアプリケーションを追加し、コンテナイメージをビルドします。次に、ビルドしたコンテナイメージからコンテナを実行し、必要なテストを実行後、OKであればコンテナイメージをレジストリーにプッシュします。そして、コンテナイメージから仮想マシンまたはサーバーを実行するためのディスクイメージを作成します。ディスクイメージの形式は、QCOW2、AMI、VMDK、ISOなどがサポートされます。最終的には、作成したディスクイメージから、コンテナイメージを仮想マシンやベアメタルシステムにデプロイした後、必要なテストを実行します。 Containerfile (Dockerfile) からコンテナイメージをビルド コンテナイメージのテスト コンテナイメージのレジストリーへのプッシュ コンテナイメージからベースディスクイメージの作成 コンテナイメージのデプロイ システムのテスト RHEL Bootc ベースイメージは、 Red Hat Ecosystem Catalog から入手できます。 オペレーティングシステムのアップデート (Day2 オペレーション) Day1 オペレーションのワークフローの実行は最初の一度きりですが、Day2 オペレーションは、コンテナイメージの変更の都度実行されることになります。それぞれのタスクは、Day1 オペレーションとほぼ同じですが、一つ大きな違いは、 4.コンテナイメージの切り替えとシステムの再起動 です。コンテナイメージはイミュータブルですので、一度デプロイされたオペレーティングシステムへの変更は、従来のように dnf パッケージマネージャーを使いません。Image Modeでは、コンテナイメージを変更した上で、新しいオペレーティングシステムの更新をコンテナレジストリーから取得して、システムを再起動させることになります。 Containerfile (Dockerfile) からコンテナイメージをビルド コンテナイメージのテスト コンテナイメージのレジストリへのプッシュ コンテナイメージの切り替えとシステムの再起動 システムのテスト それでは上記のワークフローを、例としてAWS上でAnsible Automation Platform(AAP)を活用して、自動化してみましょう。 想定環境 ここでは、AAPのControllerが稼働する aac01 があり、コンテナのビルド用に builder01 が稼働しています。Image Mode for RHELのVMは bootc01 で、アプリケーションとしてhttpdが稼働します。また、イメージレジストリとして quay.io 、Gitリポジトリとして GitHub を想定します。 Ansible Automation Platform (AAP) Ansible Automation Platform(AAP)では、Workflow Jobという形で自動化されたそれぞれのJobを、ワークフロー形式で実行することができます。 こちらは、 Day1 オペレーション のワークフローの例です。 Job やっていること Build Bootc Image コンテナイメージのビルドとテスト、レジストリーへのプッシュ Deregister Bootc AMI Amazon EC2 AMIの登録解除 Create Bootc AMI bootc-image-builder を使ったコンテナイメージからAMIイメージの作成と登録 Deploy Bootc VM 作成したAMIからAWSインスタンスのデプロイ Test Bootc App AWSインスタンス上のアプリケーション(httpd)のテスト そして次に示すのは、システムのアップデート用のいわゆる Day2 オペレーション のワークフローの例です。 Job やっていること Build Bootc Image コンテナイメージのビルドとテスト、レジストリーへのプッシュ Update Bootc VM bootc コマンドを使ったコンテナイメージへの参照の切り替えとインスタンスの再起動 Test Bootc App AWSインスタンス上のアプリケーション(httpd)のテスト Day2 オペレーションのワークフローについては、AAP上で GitHub Webhook の設定をすることで、GitHub上のContainerfileの変更をトリガーにワークフローを起動させ、GitOpsのアプローチを実現することができます。また、例示はしていませんが、テストが失敗した場合に即座に再度 bootc コマンドを使い、コンテナイメージを切り替えてロールバックするようなJobを起動することも可能です。 まとめ ここでは、Image Mode for RHELを使った仮想マシン(VM)を、Ansibleを使ってデプロイからアップデートを自動化する方法について、AWSの環境を例にしてご紹介しました。Image Modeについては、これまでのコンテナ化されたアプリケーションと同じように、GitOpsや継続的インテグレーション/継続的デリバリー(CI/CD)などのコンセプトを適用し、オペレーティングシステム全体を管理できるものとして各所で期待されています。例ではAnsibleを使いましたが、コンテナのビルド自体は様々な3rd Partyのサービスで実行してもよいですし、アプリケーションのビルドプロセスと統合することもできるかと思います。今回は、サーバーサイドの long-lived process をImage Mode for RHELで動作させるアプリケーションとして例示しましたが、実は先日GAした Red Hat Enterprise Linux AI もImage Modeをベースとしています。今後ますますユースケースが増えそうなImage Modeを、皆さんも一度試してみてはいかがでしょうか? ちなみに、ここで説明したサンプルは、以下のGithubリポジトリから取得して、簡単に再現することが可能です。興味を持たれた方は、ぜひCloneしてトライしてみてください。 https://github.com/yukshimizu/bootc-rhel-management-setup https://github.com/yukshimizu/bootc-rhel-management-demo
OpenShift Advent Calendar 2024 の12/17の記事です。 Red Hatの小島です。 Red Hat OpenShift Service on AWS(ROSA)ではセキュリティを考慮してAWS STS(Security Token Service)を利用したデプロイと運用を推奨しており、ROSA with HCPクラスターをデプロイする際は、AWS STSの利用を必須としています。本記事ではAWSユーザーから聞かれることの多いAmazon EFSとAmazon ECRについて、専用のOperatorからAWS STSの認証情報で利用する方法の概要をご紹介します。なお、ROSA環境からAWS STSを利用してAWSリソースにアクセスする仕組みの解説は下記のブログに記載されていますので、こちらも併せてご参照ください。 qiita.com 注: 本記事にあるECR Secret Operatorを利用する時、ROSA/OpenShiftのバージョン4.17系では4.17.7以降をご利用ください。 ECR Secret OperatorはROSA/OpenShift バージョン4.16系までの環境で機能します。ROSA/OpenShift バージョン4.17系の環境では機能しないのでご注意ください。 AWS Elastic File Service CSI Driver Operatorの利用 AWS側の準備 ROSA側の準備 Amazon EFSのファイルシステム利用 Amazon EFSを利用した静的PVの作成 ECR Secret Operatorの利用 AWS側の準備 ROSA側の準備 Amazon ECRのプライベートリポジトリ認証情報取得 Amazon ECRのプライベートリポジトリのコンテナイメージプッシュとプル 参考情報 AWS Elastic File Service CSI Driver Operatorの利用 OpenShiftやROSAではAmazon EKSと同様に、Amazon EFSのContainer Storage Interface(CSI)ドライバーを使用して永続ボリュームをプロビジョニングできるようになっています。Amazon EFSのCSIドライバーを簡単に利用するためのOperatorが、OpenShiftのOperatorHubで「AWS Elastic File Service CSI Driver Operator」という名前で提供されています。このOperatorでインストールできるCSIドライバーによって、Amazon EFSの動的プロビジョニングと静的プロビジョニングが可能になります。 AWS側の準備 AWS Elastic File Service CSI Driver Operatorを利用するための前準備として、Amazon EFSを利用するためのAWS IAMロールとポリシーを最初に作成します。これについては、前述のブログで触れている ccoctlを使う手順 もありますが、ここではAWSのCLIやコンソールを使って作成することにします。 次のコマンドで、Amazon EFSを利用するためのIAMポリシーを作成します。 $ cat << EOF > efs-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "elasticfilesystem:DescribeAccessPoints", "elasticfilesystem:DescribeFileSystems", "elasticfilesystem:DescribeMountTargets", "elasticfilesystem:TagResource", "ec2:DescribeAvailabilityZones" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "elasticfilesystem:CreateAccessPoint" ], "Resource": "*", "Condition": { "StringLike": { "aws:RequestTag/efs.csi.aws.com/cluster": "true" } } }, { "Effect": "Allow", "Action": "elasticfilesystem:DeleteAccessPoint", "Resource": "*", "Condition": { "StringEquals": { "aws:ResourceTag/efs.csi.aws.com/cluster": "true" } } } ] } EOF $ aws iam create-policy \ --policy-name rosa-efs-csi-policy \ --policy-document file://./efs-policy.json \ --query 'Policy.Arn' --output text arn:aws:iam::<AWS_ACCOUNT_ID>:policy/rosa-efs-csi-policy IAMロールを作成して、先ほど作成したIAMポリシーを割り当てます。この時、ROSAクラスターで利用している OpenID Connect (OIDC) IDプロバイダー のARNを指定します。このIAMロールによって、指定したOIDC IDプロバイダーを利用するROSAクラスターの特定のサービスアカウントがAWSリソースにアクセスするための、一時的な認証情報が自動的にリクエストされるようになります。 $ rosa list oidc-providers I: Fetching OIDC providers OIDC PROVIDER ARN Cluster ID In Use arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.op1.openshiftapps.com/289dfj5mirXXXXXX 2el3camm8eh4eq8p19vtcm9n0iujmggq Yes $ cat <<EOF > efs-trust.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.op1.openshiftapps.com/289dfj5mirXXXXXX" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.op1.openshiftapps.com/289dfj5mirXXXXXX:sub": [ "system:serviceaccount:openshift-cluster-csi-drivers:aws-efs-csi-driver-operator", "system:serviceaccount:openshift-cluster-csi-drivers:aws-efs-csi-driver-controller-sa" ] } } } ] } EOF $ aws iam create-role \ --role-name rosa-efs-csi-role \ --assume-role-policy-document file://./efs-trust.json \ --query "Role.Arn" --output text arn:aws:iam::<AWS_ACCOUNT_ID>:role/rosa-efs-csi-role $ aws iam attach-role-policy \ --role-name rosa-efs-csi-role \ --policy-arn arn:aws:iam::<AWS_ACCOUNT_ID>:policy/rosa-efs-csi-policy 続いて、ROSAクラスターと同じAWSリージョンにAmazon EFSのファイルシステムを作成します。Amazon EFSのコンソールにアクセスして、「ファイルシステムの作成」から「カスタマイズ」を選択します。 「ステップ1: ファイルシステムの作成」はデフォルトのパラメーターを全て利用します。ここでは、マルチAZ(デフォルト)とシングルAZのどちらのファイルシステムにするかを選択できますが、デフォルトのマルチAZのままにしておいて「ステップ2: ネットワークアクセス」に進みます。 「ステップ2: ネットワークアクセス」ではROSAクラスターが利用するVPCと、ワーカーノードが利用するプライベートサブネットIDを指定してマウントターゲットを作成します。この画像はROSAクラスターをシングルAZ構成で作成している時の例です。マルチAZ構成のROSAクラスターを利用する場合は、各AZでワーカーノードが利用するプライベートサブネットごとにマウントターゲットを追加していくことになります。例えば、3つのAZのワーカーノードを利用するROSAクラスターの場合は、3つのマウントターゲットを作成する必要があります。 セキュリティグループは、ROSAクラスターが利用しているものでなくても大丈夫です。VPCを作成した時にデフォルトで作成されるセキュリティグループなどを指定できます。「次へ」から「ステップ3: ファイルシステムポリシー」に進みます。 「ステップ3: ファイルシステムポリシーは」全てデフォルトのパラメーターのままにしておいて、「ステップ4」で確認したら「作成」をクリックして、ファイルシステムの作成を完了します。作成したファイルシステムのID(fs-XXXXX)は後で利用しますので、メモしておきます。 先ほどファイルシステムを作成した時に指定したセキュリティグループで、NFSを利用するためのTCP2049ポートを開けておきます。セキュリティグループの「インバウンドのルールを編集」画面で、「NFS」タイプとROSAクラスターのワーカーノードのCIDR(下記画像の例では 10.0.0.0/16 )を指定するインバウンドルールを追加して、ルールを保存します。これでAWS側の準備は完了です。 ROSA側の準備 ROSAクラスターに cluster-admin などの管理ユーザーでログインして、OpenShiftコンソールのOperatorHubからAWS EFS CSI Driver Operatorをインストールします。「AWS EFS CSI」などのキーワードでOperatorを検索および選択してインストールします。 「ロールARN」では「AWS側の準備」の項目で作成したIAMロールのARNを指定します。また、「更新の承認」が「手動」になっていた場合「自動」を選択して、残りはデフォルトのパラメーターでインストールします。インストールをクリックして数分待つと、Operatorのインストールが完了します。 AWS EFS CSI Driver Operatorを使って、Amazon EFS CSIドライバーをインストールします。OpenShiftコンソールの「管理」メニューの「CustomResourceDefinitions」から「ClusterCSIDriver」をクリックして、「インスタンス」タブの「ClusterCSIDriverの作成」をクリックします。ちなみに、この画面ではAmazon EBS CSI用に ebs.csi.aws.com という名前のClusterCSIDriverがデフォルトで作成済みであることを確認できます。これによって、ROSAクラスターは最初からAmazon EBSをストレージクラスとして利用できるようになっています。 下記をコピペして「作成」をクリックして efs.csi.aws.com という名前のClusterCSIDriverを作成します。 apiVersion: operator.openshift.io/v1 kind: ClusterCSIDriver metadata: name: efs.csi.aws.com spec: managementState: Managed 「作成」をクリックした後に表示される画面で、以下の2つの条件が「True」になるのを待ちます。ここまでの設定間違いがない場合は、すぐに「True」になることを確認できるはずです。 AWSEFSDriverNodeServiceControllerAvailable AWSEFSDriverControllerServiceControllerAvailable Amazon EFSのファイルシステムを利用するためのストレージクラスを、OpenShiftコンソールの「StorageClasses」メニューから作成します。以下は efs.csi.aws.com ClusterCSIDriverを利用して efs-csi という名前のストレージクラスを作成するための例です。ここではAmazon EFS CSIドライバーの動的プロビジョニングを利用することを前提としています。 kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: efs-csi provisioner: efs.csi.aws.com parameters: provisioningMode: efs-ap fileSystemId: fs-00d1cfae4484ba25d directoryPerms: "700" gidRangeStart: "1000" gidRangeEnd: "2000" basePath: "/dynamic_provisioning" 各パラメーターの解説は次のドキュメントをご参照ください。 docs.redhat.com これによって efs-csi という名前のストレージクラスが作成されます。 これでROSA側の準備も完了です。 Amazon EFSのファイルシステム利用 これまでの手順で作成した efs-csi ストレージクラスを利用して、Amazon EFSのファイルシステムをROSAクラスターから利用してみます。OpenShift上で適当なプロジェクト(下記画像の例では test-project01 )を作成して、その中にPVCを作成します。複数のワーカーノードから同時に読み書きできるようにするために、 アクセスモード は 共有アクセス(RWX) を指定します。PVCの名前とサイズは適宜指定して「作成」をクリックします。 PVCの作成が完了すると、 efs-csi ストレージクラスのボリュームバイディングモードが Immediate のために、即座にAmazon EFSのファイルシステムのアクセスポイントにバウンドされます。 なお、PVCが作成されると、Amazon EFS CSIドライバーの動的プロビジョニングによってアクセスポイントが自動作成されていきます。 efs-csi ストレージクラス作成時に指定したグループIDが利用されます。前述したストレージクラスの例だと gidRangeStart: 1000 と gidRangeEnd: 2000 を指定しているので、1000から2000 の未使用のグループIDの中で最も小さい番号が使われていきます。PVCを消すと、該当するAmazon EFSのアクセスポイントも自動的に削除されます。 このテスト用のPVC test-pvc-01 を利用するPodを作成してみます。OpenShiftコンソール右上の「+」アイコンから、下記のYAMLを入力して「作成」をクリックします。 apiVersion: v1 kind: Pod metadata: name: test-efs-01 namespace: test-project01 spec: volumes: - name: efs-storage-vol persistentVolumeClaim: claimName: test-pvc-01 containers: - name: test-efs image: centos:latest command: [ "/bin/bash", "-c", "--" ] args: [ "while true; do touch /mnt/efs-data/verify-efs && echo 'hello efs' && sleep 30; done;" ] volumeMounts: - mountPath: "/mnt/efs-data" name: efs-storage-vol securityContext: allowPrivilegeEscalation: false seccompProfile: type: RuntimeDefault これで test-efs-01 という名前のPodが作成されて、「hello efs」ログや、コンテナ内にマウントされた /mnt/efs-data ディレクトリの読み書きを確認できます。 また、 test-pvc-01 PVCを利用する他のPodを test-efs-01 Podと同様に test-efs-02 などの名前のPodとして作成すると、他のPodからも test-pvc-01 PVCにあるデータの読み書きが可能なことを確認できます。確認が終了してAmazon EFSのファイルシステムを削除したい場合、PVCを利用しているPod、PVC、ストレージクラス、EFSファイルシステムの順番に削除してください。 Amazon EFSを利用した静的PVの作成 ここまではAmazon EFS CSIドライバーの動的プロビジョニングによるアクセスポイントの自動作成を紹介してきましたが、特定のアクセスポイントを <EFSファイルシステムID>::<アクセスポイントID> のように指定して、 静的なPVを作成 してPodから利用することもできます。これは、Amazon EFSのバックアップやリストアのために作成されたEFSファイルシステムやそのアクセスポイントを直接指定したいといった場合に有効なシナリオです。この場合は、次のようなYAMLでPVを作成します。EFSファイルシステムのルートディレクトリを指定する場合は volumeHandle: <ファイルシステムID> というように、ファイルシステムIDだけを指定します。 apiVersion: v1 kind: PersistentVolume metadata: name: efs-static-pv-01 spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteMany - ReadWriteOnce claimRef: kind: PersistentVolumeClaim name: test-static-pvc-01 persistentVolumeReclaimPolicy: Retain storageClassName: efs-static-csi csi: driver: efs.csi.aws.com volumeHandle: fs-00d1cfae4484ba25d::fsap-0a7d8a0cc1d4a11ab volumeAttributes: encryptInTransit: "true" このPVで指定している擬似的なストレージクラス efs-static-csi を指定したPVCを作成できます。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-static-pvc-01 spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: efs-static-csi ここで test-static-pvc-01 PVCが不要になって削除した後に、別のPVCから efs-static-pv-01 PVを再利用したい場合、 test-static-pvc-01 PVCのclaimデータをPVのYAMLから削除する必要があります。下記画像の claimRef: から下の選択している部分を削除します。なお、動的プロビジョニングの場合と異なり、静的PVを利用している場合はPVCやPVを削除してもアクセスポイントは自動削除されないため、不要になったアクセスポイントは手動削除してください。 ECR Secret Operatorの利用 ROSAやSelf-Managed OpenShift on AWSを使っている場合、OpenShiftクラスターの共通リポジトリとしてAmazon ECRを使っているケースもあると思います。Amazon ECRのプライベートリポジトリからコンテナイメージを取得するにはAmazon IAMベースの認証を必要としますが、 認証トークンの有効時間は12時間 であり、12時間ごとに認証トークンの再取得が求められます。認証トークンの取得と再取得を自動化するためのOperatorがECR Secret Operatorです。 ECR Secret Operatorは コミュニティーOperator とカテゴライズされていて、 Red Hatからの正式サポートは提供していません ので、注意してください。前述したAWS Elastic File Service CSI Driver OperatorはRed Hat Operatorとカテゴライズされていて、Red Hatからの正式サポートを提供します。 AWS側の準備 ECR Secret Operatorを利用するための前準備として、最初にAmazon ECRのプライベートレジストリに ecr-private01 リポジトリを作成します。リポジトリ作成手順には、ROSAやOpenShift特有のものはありませんので、Amazon ECRのコンソールか下記のようなawsコマンドなどで作成してください。 $ aws ecr create-repository --repository-name ecr-private01 { "repository": { "repositoryArn": "arn:aws:ecr:us-east-2:<AWS_ACCOUNT_ID>:repository/ecr-private01", "registryId": "<AWS_ACCOUNT_ID>", "repositoryName": "ecr-private01", "repositoryUri": "<AWS_ACCOUNT_ID>.dkr.ecr.us-east-2.amazonaws.com/ecr-private01", "createdAt": "2024-12-13T14:29:47.031000+09:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": false }, "encryptionConfiguration": { "encryptionType": "AES256" } } } 次に、Amazon ECRの認証トークンを取得するためのIAMポリシーを作成します。 $ cat <<EOF > ecr-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken" ], "Resource": "*" } ] } EOF $ aws iam create-policy \ --policy-name rosa-ecr-login-policy \ --policy-document file://./ecr-policy.json \ --query 'Policy.Arn' --output text arn:aws:iam::<AWS_ACCOUNT_ID>:policy/rosa-ecr-login-policy AWS STSを利用するためのIAMロールを作成して、先ほど作成したIAMポリシーを割り当てます。 $ rosa list oidc-providers I: Fetching OIDC providers OIDC PROVIDER ARN Cluster ID In Use arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.op1.openshiftapps.com/289dfj5mirXXXXXX 2el3camm8eh4eq8p19vtcm9n0iujmggq Yes $ cat <<EOF > ecr-trust.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.op1.openshiftapps.com/289dfj5mirXXXXXX" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.op1.openshiftapps.com/289dfj5mirXXXXXX:sub": [ "system:serviceaccount:ecr-secret-operator:ecr-secret-operator-controller-manager" ] } } } ] } EOF $ aws iam create-role \ --role-name rosa-ecr-login-role \ --assume-role-policy-document file://./ecr-trust.json \ --query "Role.Arn" --output text arn:aws:iam::<AWS_ACCOUNT_ID>:role/rosa-ecr-login-role $ aws iam attach-role-policy \ --role-name rosa-ecr-login-role \ --policy-arn arn:aws:iam::<AWS_ACCOUNT_ID>:policy/rosa-ecr-login-policy 先ほど作成したIAMロールでリポジトリのイメージ操作ができるようにするためのポリシーを、最初に作成したプライベートレジストリの ecr-private01 リポジトリに割り当てます。 $ cat <<EOF > repo-policy.json { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPushPull", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<AWS_ACCOUNT_ID>:role/rosa-ecr-login-role" ] }, "Action": [ "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:CompleteLayerUpload", "ecr:GetDownloadUrlForLayer", "ecr:InitiateLayerUpload", "ecr:PutImage", "ecr:UploadLayerPart" ] } ] } EOF $ aws ecr set-repository-policy --repository-name ecr-private01 --policy-text file://./repo-policy.json { "registryId": "<AWS_ACCOUNT_ID>", "repositoryName": "ecr-private01", "policyText": "{\n \"Version\" : \"2012-10-17\",\n \"Statement\" : [ {\n \"Sid\" : \"AllowPushPull\",\n \"Effect\" : \"Allow\",\n \"Principal\" : {\n \"AWS\" : \"arn:aws:iam::<AWS_ACCOUNT_ID>:role/rosa-ecr-login-role\"\n },\n \"Action\" : [ \"ecr:BatchGetImage\", \"ecr:BatchCheckLayerAvailability\", \"ecr:CompleteLayerUpload\", \"ecr:GetDownloadUrlForLayer\", \"ecr:InitiateLayerUpload\", \"ecr:PutImage\", \"ecr:UploadLayerPart\" ]\n } ]\n}" } ここでポリシーを割り当てた結果は、Amazon ECRコンソールのリポジトリの「パーミッション」から確認できます。これでAWS側の準備は完了です。 ROSA側の準備 ROSAクラスターのOpenShiftコンソールに cluster-admin などの管理ユーザーでログインして、OperatorHubからECR Secret Operatorをインストールします。インストールには全てデフォルトのパラメーターを利用します。これによって ecr-secret-operator プロジェクトが存在しない場合に新規作成されます。 ECR Secret OperatorがAWS STSを利用するための aws-ecr-cloud-credentials シークレットを ecr-secret-operator プロジェクトに作成します。このシークレットでは、「AWS側の準備」の項目で作成したIAMロールのARNを指定します。OpenShiftコンソールの左サイドメニューの「シークレット」から、「作成」→「キーと値のシークレット」とクリックして、パラメーターは下記の値を指定して作成します。 シークレット名: aws-ecr-cloud-credentials キー: credentials 値: 下記の3行を指定 [default] role_arn = arn:aws:iam::<AWS_ACCOUNT_ID>:role/rosa-ecr-login-role web_identity_token_file = /var/run/secrets/openshift/serviceaccount/token これでROSA側の準備も完了です。 Amazon ECRのプライベートリポジトリ認証情報取得 ECR Secret Operatorを利用してプライベートリポジトリの認証情報を取得してみます。適当なプロジェクト(下記画像の例では test-project01 )をOpenShiftコンソールから作成した後に、インストールしたECR Secret Operatorから「Secret」の下にある「インスタンスの作成」をクリックして、プライベートリポジトリの認証情報を保存するシークレットリソースを作成します。 下記のYAMLを「YAMLビュー」からコピペしてECR Secret Operatorが管理する ecr-secret-01 シークレットを作成します。この ecr-secret-01 シークレットによって、10時間ごと( frequency: 10h で指定)に自動取得したプライベートリポジトリの認証情報が、 test-project01 プロジェクトの ecr-auto-generated-secret-01 シークレットに自動保存されます。 apiVersion: ecr.mobb.redhat.com/v1alpha1 kind: Secret metadata: name: ecr-secret-01 namespace: test-project01 spec: generated_secret_name: ecr-auto-generated-secret-01 ecr_registry: <AWS_ACCOUNT_ID>.dkr.ecr.us-east-2.amazonaws.com frequency: 10h region: us-east-2 すると、以下のように ecr-secret-01 によって ecr-auto-generated-secret-01 シークレットが自動作成されていることが確認できます。 ecr-auto-generated-secret-01 の中身を見ると、プライベートリポジトリの認証情報(ユーザー名: AWS, パスワード: ランダム文字列)が保存されていることが分かります。 Amazon ECRのプライベートリポジトリのコンテナイメージプッシュとプル この自動取得した認証情報を利用して、コンテナイメージのビルドとプッシュをしてみます。Rubyのサンプルアプリケーションのソースコードをもとに、コンテナイメージをビルドしてAmazon ECRのプライベートリポジトリにプッシュするための サンプルYAMLファイル を下記のように修正して、 sample-build-config.yaml という名前で保存したYAMLファイルを利用します。 kind: BuildConfig apiVersion: build.openshift.io/v1 metadata: name: ruby-sample-build namespace: test-project01 spec: runPolicy: Serial source: git: uri: "https://github.com/openshift/ruby-hello-world" strategy: sourceStrategy: from: kind: "ImageStreamTag" name: "ruby:2.5" incremental: true output: to: kind: "DockerImage" name: "<AWS_ACCOUNT_ID>.dkr.ecr.us-east-2.amazonaws.com/ecr-private01:latest" postCommit: script: "bundle exec rake test" namespace は利用しているOpenShiftのプロジェクト名(ここでは test-project01 )に変更します。 output の箇所ではECRのプライベートリポジトリのURIに変更します。このYAMLファイルをもとにして、下記のコマンドを実行してコンテナイメージをビルドしてプライベートリポジトリにプッシュします。 $ oc project test-project01 $ oc secrets link builder ecr-auto-generated-secret-01 --for=pull $ oc create imagestream ruby $ oc tag openshift/ruby:2.5-ubi8 ruby:2.5 $ oc apply -f sample-build-config.yaml $ oc start-build ruby-sample-build --wait これらのコマンドの解説は下記です。 OpenShiftコンソールのWeb Terminal で実行できます。 oc secrets link コマンドで、自動作成された ecr-auto-generated-secret-01 シークレットを builder サービスアカウントに紐付けます。 builder サービスアカウントはOpenShiftのプロジェクト作成時に自動作成されるデフォルトのサービスアカウントの1つであり、コンテナイメージのビルド/ビルド中のイメージプル/レジストリへのイメージプッシュ、に利用されます。 --for=pull オプションで、コンテナイメージプルとプッシュの時に利用するシークレットリソースに紐付けることを指定します。デフォルトのサービスアカウントの詳細については、下記をご参照ください。 docs.redhat.com ruby イメージストリーム を test-project01 プロジェクトに作成して、 openshift プロジェクトにあるイメージストリームを利用できるように oc tag コマンドでタグ付けします。これによって、Ruby 2.5をベースとしたUBI8のコンテナイメージを、イメージビルド専用のコンテナイメージとして利用できるようになります。 コンテナイメージビルド用の設定である ruby-sample-build BuildConfigを sample-build-config.yaml ファイルから作成して、 oc start-build コマンドでコンテナイメージのビルドとプッシュを実行します。 前述した oc secrets link コマンド以外にも、OpenShiftコンソールからYAMLファイルを直接編集して builder サービスアカウントへのシークレット紐付けが可能です。 コンテナイメージのビルドとプッシュが正常に完了すると、Amazon ECRのコンソールからリポジトリにイメージがプッシュされたことを確認できます。 リポジトリにプッシュされたイメージからコンテナアプリをデプロイしてみます。 test-project01 プロジェクトを選択したままにして、OpenShiftコンソールの左サイドメニューの「開発者」→「+追加」から「コンテナーイメージ」をクリックします。 「外部レジストリーからのイメージ名」で、前述の手順でコンテナイメージがプッシュされたAmazon ECRのプライベートリポジトリのイメージURIを指定します。コンテナイメージプルのための認証情報は、前述した手順で作成した ecr-auto-generated-secret-01 シークレットが自動的に利用されます。残りのパラメーターはデフォルトのままにしておいて「作成」をクリックすることで「コンテナイメージのプル」→「コンテナアプリのデプロイ」→「コンテナアプリ公開のためのURL作成」を自動実行します。 「Routes」に記載してあるURLをクリックして、下記のようなメッセージが表示されればアプリケーションのデプロイは成功です。サンプルアプリケーションのソースコードで指定してあるデータベースをデプロイしていないためにデータベースが実行されていないというエラーメッセージが出力されますが、Amazon ECRの利用テストを目的としているため、ここでは気にしないことにします。 Welcome to an OpenShift Demo App! (It looks like the database isn't running. This isn't going to be much fun.) ちなみに、ECR Secret Operatorで作成している ecr-secret-01 などのSecretインスタンスから各プロジェクトに自動作成された ecr-auto-generated-secret-01 などのSecretリソースは、Secretインスタンスを削除しても自動削除されないので手動削除する必要があります。SecretインスタンスやSecretリソースを削除してAmazon ECRのプライベートリポジトリが不要になった場合は、AWSコンソールやawsコマンドでプライベートリポジトリも適宜削除してください。 参考情報 docs.redhat.com cloud.redhat.com
 こんにちは、Red Hatでソリューションアーキテクトをしている石川です。 先日OpenShift AIのバージョン2.16がリリースされました。 現在OpenShift AIは非常にハイペースでリリースが行われており、約1ヶ月に一度のペースで機能アップデートが行われています。12月にリリースされたバージョン2.16についても多くの機能が追加されており、その中の一つとしてマルチノードでLLMの推論を行う機能がTech Previewとして追加されました。 docs.redhat.com  LLMの推論を行う上で大事な要素として、どれだけのGPUのVRAM(メモリ)を利用できるかがあります。例えば、パラメーターが7BのLLMを量子化せずに動かそうとする場合、おおよそ必要なVRAMは以下の式で計算することができます。 7B * 2byte * 1.2= 16.8GB  パラメーターが16bit表現の場合、パラメーターごとに2byte必要となり、そこにオーバーヘッドとして1.2を乗算して、必要なVRAMは凡そ16.8GBと計算できます。実際には同じパラメーターのモデルであってもコンテクスト長などの要素により、必要なVRAM容量は変わりますが、一つの目安とすることができます。  7Bよりも大きな70B程度のサイズのモデルを動かそうとする場合、ネックとなるのがVRAMの容量です。70Bのモデルを先程の式に当てはめると、凡そ168GBのVRAM容量が必要だと計算できます。そのため、例えば、 VRAM容量が24GBとなる NVIDIAのL4では、7~8台のGPUデバイスが要求されます。  1台のノード上にこれらのGPUを備えることができれば、シングルノード上で推論を実施することができますが、そうではない場合、マルチノードでの推論を行う必要があります。前者については以前よりOpenShift AIで可能でしたが、後者については今回のバージョンアップで新たに機能が追加され、実行可能となりました。本記事ではこの機能を利用しマルチノードでの推論を実施します。  なお、Tech Preview機能は商用環境での利用を想定しておらず、サポートの対象外となります。詳しくは以下をご参照下さい。 access.redhat.com 環境の構築  まずマルチノード推論を行うために必要な環境を準備しましょう。今回はAWS上でクラスタを構成していきます。AWSでのOpenShift AIを使ったLLM推論環境のセットアップ方法については以前書いた以下の記事をご確認下さい。 rheb.hatenablog.com  上記の記事と異なるポイントを2つご紹介します。  一つ目は利用するGPUインスタンスの種類です。今回は70Bのモデルを実行するため、以下のインスタンスを2台クラスタに追加します。 ・g6.12xlarge(48vCPU,192GiB Memory, L4 GPU 24GB VRAM * 4) これによりクラスタ内で合計で8つのGPUデバイスを利用することができます。なお、AWSの東京リージョンではオンデマンドインスタンスとして利用する場合、1台あたり約$6.7の費用が発生するため、実際に試す際には利用コストに注意して下さい。    二つ目はPVです。OpenShift AIのマルチノード推論ではRWX(ReadWriteMany)のPVが必要となります。本記事ではOpenShift Data Foundationの ocs-storagecluster-cephfs StorageClassを利用します。ODFのインストール方法については、 公式ドキュメント の記載を参照して下さい。ROSA HCP環境を利用する場合は、必要な権限が付与された IAMロールの作成とARNの設定 が求めらるため、適宜設定を行って下さい。  これでマルチノード推論を行うのに必要な準備が整いました。 利用対象のLLM  今回利用するのは先日Meta社より発表されたLlama3.3です。 Meta公式のXのポスト によると、モデルのアラインメントチューニングの改善、オンライン強化学習の適用により、70Bというモデルサイズでありながら、Llama3.1の405B相当の性能となっているとのことです。  モデルはHugging Face上で公開されていますが、Gated Modelとなっているため、アクセスには個人情報の登録や規約への同意が必要です。必要な項目を入力し、しばらく待つと承認のメールが届き、モデルにアクセスすることができます。 huggingface.co モデルのデプロイ  それではモデルをデプロイしていきます。流れとしては以下の通りとなります。 (1) Hugging Faceからモデルを取得し、オブジェクトストレージにアップロード (2) オブジェクトストレージからRWXのPVにモデルをダウンロード (3) マルチノード推論のためのカスタムリソースを作成 順番に実施していきましょう。 (1) Hugging Faceからモデルを取得し、オブジェクトストレージにアップロード  OpenShift AIコンソール上で、Data Science Project、Data Connectionを作成し、カスタムNotebookイメージとしてODH Toolsを登録します。モデルの取得とアップロードの手順については、 前回のブログ の"OpenShift AIにおける各種設定"、"モデルのダウンロード"と同じ手順となるため、具体的な手順についてはそちらを参照して下さい。登録したODH Toolsを用いてHugging FaceのLlama3.3のページからモデルを取得しましょう。 モデルサイズが大きいため完了まで20~30分程度かかります。 (2) オブジェクトストレージからRWXのPVにモデルをダウンロード  マルチノード推論ではモデルを一度RWXのPVに保存し、それを各Podに接続、vLLMにロードします。そのためまず必要なPVCを作成します。OpenShiftのコンソール画面から以下の画像のようにPVCを作成しましょう。 StorageClass: ocs-storagecluster-cephfs 名前: model-store アクセスモード: RWX サイズ: 300GiB  このPVCを作成するプロジェクトの中で最終的なモデルの推論まで行うため、必ず(1)で作成したData Science Projectの中でPVCを作成するようにして下さい。  PVCが作成できたら以下のPodを作成します。このPodではオブジェクトストレージに保存したLLMをダウンロードし、PVをアタッチしたディレクトリに保存します。 $ cat << EOF | oc apply -f - apiVersion: v1 kind: Pod metadata: name: download-llama33-70b-instruct labels: name: download-llama33-70b-instruct spec: volumes: - name: model-volume persistentVolumeClaim: claimName: model-store restartPolicy: Never initContainers: - name: fix-volume-permissions image: quay.io/quay/busybox:latest command: ["sh"] args: ["-c", "mkdir -p /mnt/models/llama33-70b-instruct && chmod -R 777 /mnt/models"] #① volumeMounts: - mountPath: "/mnt/models/" name: model-volume containers: - resources: requests: memory: 8Gi name: download-model imagePullPolicy: IfNotPresent image: quay.io/modh/kserve-storage-initializer:rhoai-2.16 args: - 's3://my-trial-llm/meta-llama/Llama-3.3-70B-Instruct/' #② - /mnt/models/llama33-70b-instruct env: - name: STORAGE_CONFIG valueFrom: secretKeyRef: name: storage-config key: my-storage #③ volumeMounts: - mountPath: "/mnt/models/" name: model-volume EOF ①: /mnt/models/llama33-70b-instruct というディレクトリを作成し、モデルを保存。 ②: モデルが保存されたオブジェクトストレージのバケット、パスを指定。 ③: ②にアクセスするための認証情報をSecretより取得。ここでは一つ前の工程で作成したData ConnectionのSecretを指定。  作成したPodが完了状態になれば、モデルのダウンロードは完了となります。 (3) マルチノード推論のためのカスタムリソースを作成  それではマルチノード推論のためのカスタムリソースを作成しましょう。マルチノード推論はまだGUIからの作成に対応していないため、マニフェストを作成し実行します。  最初にモデルの実行環境となるServingRuntimeリソースを作成します。ServingRuntimeでは利用するコンテナイメージや、コマンド引数などの情報が登録されます。作業環境から、以下を実行して、予め準備されているテンプレートからリソースを作成しましょう。 # Project(Namespace)を変更 $ oc project multi-node-serving # ServingRuntimeの作成 oc process vllm-multinode-runtime-template -n redhat-ods-applications|oc apply -f -  テンプレートから作成されたServingRuntimeを今回のモデルに合わせてカスタマイズします。 oc edit により、vLLM実行時に渡す引数を追加します。 $ oc edit servingruntime vllm-multinode-runtime ... containers: - args: - "ray start --head --disable-usage-stats --include-dashboard false \n# wait for other node to join\nuntil [[ $(ray status --address ${RAY_ADDRESS} | grep -c node_) -eq ${PIPELINE_PARALLEL_SIZE} ]]; do\n echo \"Waiting...\"\n sleep 1\ndone\nray status --address ${RAY_ADDRESS}\n\nexport SERVED_MODEL_NAME=${MODEL_NAME}\nexport MODEL_NAME=${MODEL_DIR} \n\nexec python3 -m vllm.entrypoints.openai.api_server --port=8080 --distributed-executor-backend ray --model=${MODEL_NAME} --served-model-name=${SERVED_MODEL_NAME} --tensor-parallel-size=${TENSOR_PARALLEL_SIZE} --pipeline-parallel-size=${PIPELINE_PARALLEL_SIZE} --disable_custom_all_reduce --max-model-len=47104 --gpu-memory-utilization=0.98\n" ...  ここでは最終行の --max-model-len=47104 --gpu-memory-utilization=0.98 を新たに加えています。 Llama3.3は最大で128kのコンテクスト長に対応していますが、それを実現するにはより多くのVRAM容量が必要となるため、今回の環境で利用可能な最大の長さにコンテクスト長を制限します。   最後にモデルを表すリソースであるInferenceServiceをデプロイします。 $ cat << EOF | oc apply -f - apiVersion: serving.kserve.io/v1beta1 kind: InferenceService metadata: annotations: #① serving.kserve.io/deploymentMode: RawDeployment serving.kserve.io/autoscalerClass: external name: llama33-70b-instruct spec: predictor: model: modelFormat: name: vLLM runtime: vllm-multinode-runtime #② storageUri: pvc://model-store/llama33-70b-instruct #③ workerSpec: #④ tensorParallelSize: 4 pipelineParallelSize: 2 EOF ①: annotationsでKserveのRawDeployment(Serverlessを利用しないモード)を設定。 ②: 先ほど作成したServingRuntimeを指定。 ③: モデルを保存先のPVCとパスを指定。 ④: tensorParallelSize にはノードあたりのGPU数、 pipelineParallelSize にはGPUノード数をそれぞれ指定。( 参照 )  InferenceServiceを作成すると推論用のPodが各GPUノードで起動します。上記で設定した通り、モデル分割が行われ、それぞれのPodで起動するvLLM上にロードされます。  vLLMでマルチノードでの推論を実行するにはオープンソースのRayが用いられており、各Podが一つのRay Clusterとして機能します。  モデルが無事起動したかどうかは、Podのログを確認しましょう。 $ oc logs $(oc get pods -o name | grep predictor | grep -v worker) | less # 以下が出力されていればOK ... INFO: Uvicorn running on socket ('0.0.0.0', 8080) (Press CTRL+C to quit) INFO: 127.0.0.1:60290 - "GET /health HTTP/1.1" 200 OK INFO: 127.0.0.1:60298 - "GET /health HTTP/1.1" 200 OK INFO 12-16 06:21:24 metrics.py:349] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Swapped: 0 reqs, Pending: 0 reqs, GPU KV cache usage: 0.0%, CPU KV cache usage: 0.0%. ...  上記のログが出力され、入力トークンを待ち受けている状態となっていれば正しく動作しています。Routeを作成し、APIのアクセスエンドポイントを作成しましょう。 $ cat << EOF | oc apply -f - apiVersion: route.openshift.io/v1 kind: Route metadata: name: llama33-70b-instruct-predictor namespace: multi-node-serving spec: to: name: llama33-70b-instruct-predictor kind: Service tls: insecureEdgeTerminationPolicy: Redirect termination: edge port: targetPort: http EOF # URLの表示 $ echo https://$(oc get route llama33-70b-instruct-predictor -o "jsonpath={.spec.host}") モデルの実行  モデルがデプロイできたので、APIを実行してみましょう。今回はフロントエンドのUIに Open WebUI を利用します。以下の手順に従い、アプリケーションをデプロイしてください。 $ git clone https://github.com/JPishikawa/open-webui-openshift $ cd open-webui-openshift $ vi manifests/openwebui-cm.yaml ... data: WEBUI_AUTH: 'False' # 以下を変更 OPENAI_API_BASE_URLS: 'https://CHANGE_HERE/v1' OPENAI_API_KEYS: na ... $ chmod +x deploy.sh $ ./deploy.sh # アプリURLの表示 $ echo https://$(oc get route open-webui -o "jsonpath={.spec.host}" -n app-webui)  ブラウザからアプリにアクセスし、LLMを実行してみましょう。画面左上で、呼び出すモデルを指定し、クエリを実行します。  APIが実行され、結果が返ってくることが確認できました。体感として若干のトークン生成の遅さを感じますが、こちらについては量子化モデルを利用したり、オンプレミスであればGPUノード間のRDMA設定を行うことで改善が可能だと考えられます。 まとめ  本記事では、OpenShift AIでマルチノードによるLLM推論機能をご紹介しました。マルチノードを利用することで、今回のようにサイズの大きいモデルをホストしたり、より長いコンテクストで利用し易くなります。現在はまだTPであるため、機能として洗練されていない点もありますが、気になった方はぜひ試してみて下さい。
以前の記事 rheb.hatenablog.com で紹介した Apache Camel 向け開発ツールですが、今回は 先日(2024/12/10)リリースされた Kaoto 2.3 に関するご案内です。 ビジュアル Camel エディターとしてアップデートを重ねる Kaoto ですが、今回のマイナーアップデートにも注目すべき機能が多数あります。 特に目立つ機能を2つご紹介します。 1: 製品版 Camel ライブラリーバージョンを選択可能に コミュニティーバージョンだけでなく製品バージョンを指定できますので、より迷うことなく必要なコンポーネントを選びエディットできます。(画像は、Kaotoコミュニティーからの引用) Camelライブラリーバージョンを選択可能に 2: Data Mapperが遂に登場 (Tech Preview) ビジュアル data mapper へのニーズを耳にする機会が多かったですが、遂に Tech Preview版が公開されました。 現時点では XSLT対応のみですが、ぜひお試しいただき、フィードバックをお寄せいただければと思います。(画像は、Kaotoコミュニティーからの引用) Data Mapper (Tech Preview) Kaoto 2.3 のリリースノートはこちら。 https://kaoto.io/blog/kaoto-2.3-release/ その他、Kaotoコミュニティーが新たな活動を進めています。 Youtube channel が運営されていますが、日本語版動画がアップされ初めました。 https://www.youtube.com/@KaotoIO Kaotoの概要 www.youtube.com Kaoto データマッパー(テクニカルプレビュー)のご紹介 www.youtube.com チャンネル登録と高評価をぜひ! まずは動画で概要を把握していただき、その後はコミュニティーで提供されているワークショップ kaoto.io に挑戦してみてはいかがでしょうか。 最後に 実は弊社でも提供する Kaoto ワークショップを通して、機能改善やバグレポートを頂いております。それらは社内経由でコミュニティーへ連系され、今回のリリースにも新機能や修正が組み込まれています。 ぜひ率先してお試しいただき、感想やご要望などフィードバックしていただけるとありがたいです。コミュニティーの窓口(chat、youtube、git) もしくは 弊社の窓口(営業担当、サポート)をご利用ください。
Red Hat の古市です。 Red Hat Fuse は 既に End of Life を向かえ、Extended Life cycle support(ELS)の終了も間近に控えています。 https://access.redhat.com/product-life-cycles?product=Red%20Hat%20Fuse 皆さん、Red Hat Build of Apache Camel 4.x への移行はお済みでしょうか?順調に進んでいますでしょうか? Karaf runtime 上で、 Blueprint XML DSL を使った資産をお持ちの方が多くいらっしゃるかと思いますが、Apache Camel コミュニティーブログに、「Camel Karaf から Camel Spring Boot もしくは Camel Quarkus への移行」と題した記事が公開されました。 早速、和訳しましたので、まだ移行がお済みでない方は、ぜひ参考になさってください。 https://playintegration.blogspot.com/2024/12/camel-karaf-camel-spring-boot-camel.html あくまでもコミュニティー向けの記事となりますので、製品版での注意が必要な箇所もあります。ここでは、いくつかご案内します。 1. Spring Boot で定義する Web service dependency 製品版では、tomcat ではなく undertow の使用を推奨しておりますので、追加すべき dependency はこのようになります。 <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-web </artifactId> <exclusions> <exclusion> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-tomcat </artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-undertow </artifactId> </dependency> 2. camel-jbang を製品版では Camel CLI として提供しています。 https://docs.redhat.com/en/documentation/red_hat_build_of_apache_camel/4.8/html/tooling_guide_for_red_hat_build_of_apache_camel/index 開発ツールに対するサポート内容は特殊なものになります。詳細については、こちらからご確認いただけます。 https://access.redhat.com/articles/7043889 3. Camel 3.x/4.x の移行およびアップグレード ガイド 記事の中ではコミュニティー版をリンクしていますが、製品版のマイグレーションガイドも各種用意されています。 https://docs.redhat.com/en/documentation/red_hat_build_of_apache_camel/4.8 弊社コンサルティングサービス経由での移行支援もオプションとしてご用意しております。必要の際には、弊社担当営業までお声掛けください。 それでは、「モダンな Camel 4 の世界で会いましょう。」
※この記事は OpenShift Advent Calendar 2024 の 10日目の記事です。 qiita.com こんにちは、ストレージと OpenShift を生業にしているうつぼ(宇都宮)です。ご無沙汰しております。 ここ最近というかこの一年はすっかり OpenShift Virtualization(OCP-V)の小僧として活動させていただいております。 お陰様で OCP-V は非常に多方面から注目を浴びております。ありがとうございます。 OCP-V 小僧の活動は多忙ではありますが、良いところが多くあります。 それは OCP-V のお話をしていると、ほぼ確実にストレージの話題が出るところです。やはりドインフラな内容なので、皆様ストレージは気になるようです。 そんな中で、うつぼは普段なかなか抜かせてもらえないストレージトークの刃を日々合法的に振り回してカタルシスを感じております。ありがとうございます。 最近はそんな感じですが、今日の記事も普通に OCP-V を使う分にはあまり知られていない(そしてさほど知らなくても大丈夫な)ディスク周りのことです。 Containerized Data Importer(CDI) OCP-V で仮想マシン(VM)を作る際には VirtualMachine というカスタムリソースを作ります。これは GUI でも CLI でも同じです。 VM にはいわゆる rootdisk が絶対必要です。永続性が求められるため PVC として用意するのが必須です。 ゲスト OS のイメージを PVC に放り込んで rootdisk を作っていくわけですが、いくつかの方法があります。 既存の PVC や VolumeSnapshot からクローン Web サーバやコンテナレジストリからディスクイメージをインポート ローカルのディスクイメージをアップロード これらを実行してくれるのが、 Containerized Data Importer(CDI) です。 OpenShift Virtualization Operator でインストールすると自動的に作られるので意識することはほぼないですが、CDI はカスタムリソースとして作られます。 apiVersion: cdi.kubevirt.io/v1beta1 kind: CDI metadata: annotations: cdi.kubevirt.io/configAuthority: '' name: cdi-kubevirt-hyperconverged ...(snip) finalizers: - operator.cdi.kubevirt.io labels: app: kubevirt-hyperconverged app.kubernetes.io/component: storage app.kubernetes.io/managed-by: hco-operator app.kubernetes.io/part-of: hyperconverged-cluster app.kubernetes.io/version: 4.17.1 spec: certConfig: ca: duration: 48h0m0s renewBefore: 24h0m0s server: duration: 24h0m0s renewBefore: 12h0m0s config: featureGates: - HonorWaitForFirstConsumer - DataVolumeClaimAdoption tlsSecurityProfile: intermediate: {} type: Intermediate customizeComponents: {} infra: {} uninstallStrategy: BlockUninstallIfWorkloadsExist workload: {} Data Volume GUI で VM を作成すると、自動的に VM と同じ名前の PVC が作成されます。この PVC を調べてみると、オーナーが Data Volume と指定されています。 OCP-V の VM は生の PVC ではなく、PVC を実体とする Data Volume というカスタムリソースで扱います。 デフォルトで用意されている VM テンプレートから VM を作成すると、次のような Data Volume が自動的に作られます。 apiVersion: cdi.kubevirt.io/v1beta1 kind: DataVolume metadata: name: fedora-sapphire-possum-92 namespace: demo ownerReferences: - apiVersion: kubevirt.io/v1 blockOwnerDeletion: true controller: true kind: VirtualMachine name: fedora-sapphire-possum-92 ...(snip) spec: source: snapshot: name: fedora-fee3d6a527c8 namespace: openshift-virtualization-os-images storage: resources: requests: storage: 30Gi status: claimName: fedora-sapphire-possum-92 spec.source には、"snapshot" というセクションがありますが、これは VM テンプレートの rootdisk が VolumeSnapshot で用意されているためです。 この snapshot をソースとして、 spec.storage で指定する性質(ここでは 30Gi というだけ)の PVC にクローンします。 その結果、 status.claimName の PVC ができ上がります。 なお、rootdisk を別の方法、例えばコンテナレジストリに保管されているディスクイメージから作る場合は、次のような spec になります。 spec: source: registry: url: 'docker://quay.io/containerdisks/fedora:latest' storage: resources: requests: storage: 30Gi Data Source Data Volume は単体で作成してもよいですが、VirtualMachine のマニフェストで指定することもできます。 apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: fedora-sapphire-possum-92 namespace: demo finalizers: - kubevirt.io/virtualMachineControllerFinalize labels: app: fedora-possum-92 ...(snip) spec: dataVolumeTemplates: - apiVersion: cdi.kubevirt.io/v1beta1 kind: DataVolume metadata: creationTimestamp: null name: fedora-sapphire-possum-92 spec: sourceRef: kind: DataSource name: fedora namespace: openshift-virtualization-os-images storage: resources: requests: storage: 30Gi running: true template: ...(snip) volumes: - dataVolume: name: fedora-sapphire-possum-92 name: rootdisk ...(snip) 上のように spec.dataVolumeTemplates の中に入れ子で Data Volume の定義を記載します。 この定義の中、 spec.spec.dataVolumeTemplates.spec.sourceRef を見ると、先程の Data Volume とは違って Data Source というリソースが指定されています。 Data Source はその名の通り VM のディスクイメージを管理するカスタムリソースです。 デフォルトで用意されている VM テンプレートの中には、"Source available" というマークが付いているものがありますが、これはこのテンプレートには事前に Data Source が登録されて紐づけられているよ、ということです。 4つのテンプレートに "Source available" という青地白抜きのマーク 4つの Data Source(DS) が青地白抜きのマークに相当 ゴールデンイメージのように繰り返し使う標準化された VM イメージを作りたい場合は、そのディスクイメージを Data Source として登録してユーザに公開する方法がよいでしょう。 CDI と Data Volume と Data Source の関係 最後に CDI と Data Volume と Data Source の関係について紹介します。 CDI, Data Volume, Data Source の関係 前述のように Data Volume を作成すると Data Source からクローンなりインポートなりして仮想ディスクの PVC が作成されますが、このクローンなりインポートなりをしてくれるのが CDI です。 実際に Data Volume を作成すると、作成した namespace では、"importer-prime-XXX" という Pod が起動します。 Pod には "importer" というコンテナが起動し、Data Volume 作成時に指定した source からデータをインポートしてくれます。 以下はコンテナレジストリからディスクイメージをインポートして Data Volume を作る時の Importer Pod のログです。 [lab-user@bastion ~]$ oc get pod -n aaa NAME READY STATUS RESTARTS AGE importer-prime-b16e5647-45c9-478a-a853-4b488c84651e 1/1 Running 0 12s [lab-user@bastion ~]$ [lab-user@bastion ~]$ oc logs importer-prime-b16e5647-45c9-478a-a853-4b488c84651e I1210 07:19:04.888954 1 importer.go:107] Starting importer I1210 07:19:04.889904 1 importer.go:182] begin import process I1210 07:19:04.890015 1 registry-datasource.go:190] Copying proxy certs I1210 07:19:04.890045 1 registry-datasource.go:61] Error creating allCertDir open /proxycerts/: no such file or directory I1210 07:19:04.890109 1 data-processor.go:348] Calculating available size I1210 07:19:04.891113 1 data-processor.go:356] Checking out block volume size. I1210 07:19:04.891144 1 data-processor.go:368] Request image size not empty. I1210 07:19:04.891153 1 data-processor.go:373] Target size 32212254720. I1210 07:19:04.891169 1 data-processor.go:247] New phase: TransferScratch I1210 07:19:04.891278 1 registry-datasource.go:100] Copying registry image to scratch space. I1210 07:19:04.891289 1 transport.go:193] Downloading image from 'docker://quay.io/containerdisks/fedora:latest', copying file from 'disk' to '/scratch' I1210 07:19:06.901432 1 transport.go:217] Processing layer {Digest:sha256:c8f39d7d11433a0aa9f682ca065b3d65a6e09bb891bcf4e06faca4b8e88911b0 Size:489690908 URLs:[] Annotations:map[] MediaType:application/vnd.docker.image.rootfs.diff.tar.gzip CompressionOperation:0 CompressionAlgorithm:<nil> CryptoOperation:0} I1210 07:19:07.750464 1 transport.go:152] File 'disk/disk.img' found in the layer I1210 07:19:07.750846 1 util.go:96] Writing data... I1210 07:19:11.288706 1 registry-datasource.go:178] VM disk image filename is disk.img I1210 07:19:11.288738 1 data-processor.go:247] New phase: Convert I1210 07:19:11.288747 1 data-processor.go:253] Validating image E1210 07:19:11.296590 1 prlimit.go:156] failed to kill the process; os: process already finished I1210 07:19:11.296699 1 qemu.go:115] Running qemu-img with args: [convert -t writeback -p -O raw /scratch/disk/disk.img /dev/cdi-block-volume] I1210 07:19:11.301478 1 qemu.go:273] 0.00 I1210 07:19:11.316723 1 qemu.go:273] 1.01 I1210 07:19:11.386639 1 qemu.go:273] 2.01 I1210 07:19:11.397491 1 qemu.go:273] 3.02 I1210 07:19:11.489886 1 qemu.go:273] 4.03 I1210 07:19:11.499107 1 qemu.go:273] 5.03 I1210 07:19:11.588887 1 qemu.go:273] 6.28 I1210 07:19:11.593774 1 qemu.go:273] 7.53 ...(snip) I1210 07:19:20.453555 1 qemu.go:273] 97.92 I1210 07:19:20.481321 1 qemu.go:273] 98.98 I1210 07:19:20.533138 1 qemu.go:273] 99.99 E1210 07:19:20.790409 1 prlimit.go:156] failed to kill the process; os: process already finished I1210 07:19:20.790441 1 data-processor.go:247] New phase: Resize I1210 07:19:20.791396 1 data-processor.go:247] New phase: Complete I1210 07:19:20.791544 1 importer.go:231] {"scratchSpaceRequired":false,"preallocationApplied":false,"labels":{"instancetype.kubevirt.io/default-instancetype":"u1.medium","instancetype.kubevirt.io/default-preference":"fedora"},"message":"Import Complete"} インポートが完了すると Importer Pod は自動的に Terminate し、Data Volume は "Succeeded" となって、VM から利用できるようになります。 まとめ 以上で「OpenShift Virtualization の仮想マシンの rootdisk ってどうやって作っているの?」がおわかりになったかと思います。 よく考えると、一般的な PVC を使うコンテナアプリでは、PVC が使用可能な状態となれば Pod はすぐにマウントして起動しようとします。 OCP-V の VM の骨格は Pod と PVC ですから、インポートされ切ってない半生状態の PVC で VM が上がろうとしてもおかしくないわけです。 しかし、そうはならない。PVC にディスクイメージのインポートが終わるまでは Pod は絶対に起動しません。 これは CDI の枠組みの中で、仮想ディスクを生の PVC ではなく Data Volume として扱っているおかげです。そのおかげで、毎回キレイに VM が起動するようになっているのです。 ぶっちゃけ、イメージを指定したらいい感じに上がってきてくれるブラックボックスとして扱っても全然問題ないんですが、細かいところまできちんと作られているのが KubeVirt ひいては OpenShift Virtualization なんですよということが伝えたい独り言でした。 というわけで、今回はここまで。
Red Hat で OpenShift をサポートしている Yiyong です。この記事はOpenShift Advent Calendar 2024のエントリです。 qiita.com OpenShift 4.17 バージョンより、OpenShift 公式ドキュメントの Hosted Control Planes (HCP) の章が大幅に充実しましたので、Hosted Control Plane on AWS 公式 ドキュメント のステップを参照しながらデプロイしてみました。なお、今回は Managed Service となる ROSA with HCP ではなく、Self-Managed の OCP クラスタに HCP をデプロイするパターンを紹介しています。 HCP については用語が多く、その中に同義語も複数あり、ドキュメントにも完全には統一されていないため、こちらの記事に使用される主な2つの用語を説明します: Hosted Cluster: API エンドポイントとコントロールプレーンが Hosting Cluster でホストされている OpenShift Container Platform クラスターです。同義語:Managed Cluster Hosting Cluster: Hosted Cluster の API エンドポイントとコントロールプレーンをホストする OpenShift Container Platform クラスターです。同義語:Management Cluster 、 Hub Cluster 本記事では、Hosting Cluster として、AWS IPI でインストールした 4.17.3 のクラスタを利用しています。 まず事前準備として: MultiCluster Engine for Kubernetes Operator (MCE) を Hosting Cluster にインストールして、hcp CLI を手元にダウンロードします: ## MCE Operator をインストール $ vi mce-operator.yaml apiVersion: v1 kind: Namespace metadata: name: multicluster-engine --- apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: multicluster-engine namespace: multicluster-engine spec: targetNamespaces: - multicluster-engine --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: multicluster-engine namespace: multicluster-engine spec: sourceNamespace: openshift-marketplace source: redhat-operators channel: stable-2.7 installPlanApproval: Automatic name: multicluster-engine $ oc create -f mce-operator.yaml ## MultiClusterEngine CR を作成 $ vi mce-cr.yaml apiVersion: multicluster.openshift.io/v1 kind: MultiClusterEngine metadata: name: multiclusterengine spec: {} $ oc create -f mce-cr.yaml ## hcp CLI をダウンロード $ oc get ConsoleCLIDownload hcp-cli-download -o json | jq -r ".spec" { "description": "With the Hosted Control Plane command line interface, you can create and manage OpenShift hosted clusters.\n", "displayName": "hcp - Hosted Control Plane Command Line Interface (CLI)", "links": [ { "href": "https://hcp-cli-download-multicluster-engine.apps.yhe-blue.test.example.com/linux/amd64/hcp.tar.gz", "text": "Download hcp CLI for Linux for x86_64" }, <..snip..> ] } $ wget --no-check-certificate https://hcp-cli-download-multicluster-engine.apps.yhe-blue.test.example.com/linux/amd64/hcp.tar.gz $ tar xfz hcp.tar.gz $ mv hcp bin 続いては HCP をデプロイする前に、AWS 側で必要なリソースを作成しておきます。 具体的には、S3 bucket、S3 OIDC secret、AWS IAM role と STS credentials の作成が必要です。基本的に公式ドキュメント通り作成すれば問題がないため、ここは割愛します 。 それではいよいよ HCP のデプロイを実施します。 デフォルトの設定でデプロイする場合は、下記の1つのコマンドだけでデプロイできます。 hcp create cluster aws \ --name yhe-hosted \ --infra-id yhe-hosted \ --base-domain test.example.com \ --sts-creds /home/ec2-user/sts-creds.json \ --pull-secret /home/ec2-user/pull-secret.txt \ --region ap-northeast-1 \ --generate-ssh \ --node-pool-replicas 2 \ --namespace clusters \ --role-arn "arn:aws:iam::012345678901:role/yhe-hcp-cli-role" \ --release-image=quay.io/openshift-release-dev/ocp-release:4.16.10-multi hcp create cluster コマンドには大量のオプションが提供されていて、これらのオプションを指定することで Hosted Cluster をカスタマイズすることが可能となりますが、全てのオプションがドキュメントに網羅的に説明されていないため、利用可能なオプションについては --help で確認するようにしましょう。 一例として、上記のコマンドには --release-image オプションを指定していて、Hosted Cluster のバージョンを指定しています。このオプションを指定していない場合は最新のバージョンが使用されます。 HCP では、Hosted Cluster が Hosting Cluster と同一バージョンである必要がなく、かつ Hosting Cluster 上の複数の Hosted Cluster も同一バージョンである必要がないため、サポートされるバージョンであれば自由に指定することが可能です。 上記のコマンドを実行後、AWS 上で VPC や Subnet などの infrastructure が作成され、Hosting Cluster 側の clusters Namespace 配下に、HostedCluster CR と NodePool CR が作成されます。 Hosted Cluster のデプロイ状況を監視するためには、 oc get hostedcluster コマンドを使用します。 $ oc -n clusters get hostedcluster NAME VERSION KUBECONFIG PROGRESS AVAILABLE PROGRESSING MESSAGE yhe-hosted 4.16.10 yhe-hosted-admin-kubeconfig Completed True False The hosted control plane is available 作成途中では、 PROGRESS が Partial になっていたり、何かしらのエラーメッセージが表示される場合もありますが、しばらく時間が経つと、上記のように、 PROGRESS が Completed になり、 hosted control plane is available が表示されて、Hosted Cluster のデプロイが完了します。 NodePool についても同様に oc get nodepool コマンドで状態を確認できます。 $ oc -n clusters get nodepool NAME CLUSTER DESIRED NODES CURRENT NODES AUTOSCALING AUTOREPAIR VERSION UPDATINGVERSION UPDATINGCONFIG MESSAGE yhe-hosted-ap-northeast-1a yhe-hosted 2 2 False False 4.16.10 False False また、Hosted Control Plane はその名の通り、Hosted Cluster の Control Plane コンポーネントが Hosting Cluster 側にホストされていますので、それらのコンポーネント Pod は clusters-<Hosted Cluster Name> という Namespace 配下に存在します。 $ oc -n clusters-yhe-hosted get pods | wc -l 82 $ oc -n clusters-yhe-hosted get pods | grep kube kube-apiserver-d7b9c4547-bt4v9 5/5 Running 17 41h kube-apiserver-d7b9c4547-cttnm 5/5 Running 17 41h kube-apiserver-d7b9c4547-fx6bs 5/5 Running 16 41h kube-controller-manager-685dd87d7f-msdmm 1/1 Running 3 40h kube-controller-manager-685dd87d7f-r5f76 1/1 Running 3 40h kube-controller-manager-685dd87d7f-vvjlk 1/1 Running 3 40h kube-scheduler-6f4f9cf5c4-b4756 1/1 Running 3 41h kube-scheduler-6f4f9cf5c4-fqb4p 1/1 Running 3 41h kube-scheduler-6f4f9cf5c4-ht4nz 1/1 Running 3 41h ovnkube-control-plane-548dcdcf4f-bqgql 3/3 Running 9 41h ovnkube-control-plane-548dcdcf4f-grx92 3/3 Running 9 41h それでは Hosted Cluster の方にアクセスしてみましょう。 Hosted Cluster にアクセスするためには、kubeconfig か kubeadmin password を利用することでアクセス可能です。こちら両方とも clusters Namespace 配下の Secret に保存されています。 $ oc -n clusters get secret NAME TYPE DATA AGE builder-dockercfg-fc2qb kubernetes.io/dockercfg 1 41h default-dockercfg-dgl72 kubernetes.io/dockercfg 1 41h deployer-dockercfg-8h99k kubernetes.io/dockercfg 1 41h yhe-hosted-admin-kubeconfig Opaque 1 41h yhe-hosted-etcd-encryption-key Opaque 1 41h yhe-hosted-kubeadmin-password Opaque 1 41h yhe-hosted-pull-secret Opaque 1 41h yhe-hosted-ssh-key Opaque 2 41h $ oc extract secret/yhe-hosted-admin-kubeconfig -n clusters kubeconfig $ mv kubeconfig yhe-hosted.kubeconfig $ oc --kubeconfig=yhe-hosted.kubeconfig get nodes NAME STATUS ROLES AGE VERSION ip-10-0-128-184.ap-northeast-1.compute.internal Ready worker 41h v1.29.7+4510e9c ip-10-0-143-38.ap-northeast-1.compute.internal Ready worker 41h v1.29.7+4510e9c $ oc --kubeconfig=yhe-hosted.kubeconfig get co NAME VERSION AVAILABLE PROGRESSING DEGRADED SINCE MESSAGE console 4.16.10 True False False 41h csi-snapshot-controller 4.16.10 True False False 41h dns 4.16.10 True False False 6h37m image-registry 4.16.10 True False False 41h ingress 4.16.10 True False False 16m insights 4.16.10 True False False 41h kube-apiserver 4.16.10 True False False 41h kube-controller-manager 4.16.10 True False False 41h kube-scheduler 4.16.10 True False False 41h kube-storage-version-migrator 4.16.10 True False False 41h monitoring 4.16.10 True False False 16m network 4.16.10 True False False 41h node-tuning 4.16.10 True False False 41h openshift-apiserver 4.16.10 True False False 41h openshift-controller-manager 4.16.10 True False False 41h openshift-samples 4.16.10 True False False 41h operator-lifecycle-manager 4.16.10 True False False 41h operator-lifecycle-manager-catalog 4.16.10 True False False 41h operator-lifecycle-manager-packageserver 4.16.10 True False False 41h service-ca 4.16.10 True False False 41h storage 4.16.10 True False False 41h これで一番ベーシックな HCP on AWS のデプロイが完了になります。 最後にはいくつのカスタマイズ項目を説明します。 External DNS の有効化 デフォルトでは、Hosted Cluster 側のいくつの Route が Hosting Cluster 側の Ingress ドメインを使用するようになっているため、管理上の理由で、Hosting Cluster 側の Ingress ドメインを Expose したくない場合は、External DNS の有効化をすることで、Hosting Cluster の Ingress ドメインとは別のドメインを使用するように設定することができます。 External DNS を有効にするためには、AWS 側で新しい Public DNS hosted zone を作成して、Hosting Cluster の local-cluster Namespace 配下に hypershift-operator-external-dns-credentials という Secret を作成した後、 hcp create cluster aws コマンドに --external-dns-domain オプションを指定して実行すれば、External DNS を使用するように Hosted Cluster が作成されます。 Private hosted cluster の作成 内部からの使用のみが想定されている場合は、Public からアクセスできない Private な Hosted Cluster を作成することができます。 Private Hosted Cluster を作成するためには、AWS PrivateLink を有効化するように、Hosting Cluster の local-cluster Namespace 配下に hypershift-operator-private-link-credentials という Secret を作成した後、 hcp create cluster aws コマンドに --endpoint-access Private オプションを指定して実行すれば、Private Hosted Cluster が作成されます。 Private Hosted Cluster にアクセスするためには、kubeconfig ファイルを踏み台となる bastion サーバにコピーして、bastion サーバからアクセスする必要があります。 Reference: Documentation - OpenShift Container Platform 4.17 / Hosted control planes / Deploying hosted control planes / Deploying hosted control planes on AWS
メッセージ監視 はじめに OpenShift Cluster Logging Ruler メッセージ監視の通知先の AlertManager 利用するアプリとメッセージ監視ルール アラート監視の設定の有効化 パターン1: 管理者用の AlertManager への通知 パターン3: 利用者用の AlertManager への通知 まとめ メッセージ監視 はじめに 急に冷え込んできました。OpenShift Advent Calendar 2024 の 7 日目の記事です。先日 5日目の記事 でアラート通知先がどのように変えられるかを確認しました。 本日は、Cluster Logging 機能の1つであるカスタムアラートの、メッセージ監視を試してみようと思います。 qiita.com OpenShift Cluster Logging Cluster Logging 6 からは、Elasticsearch の提供が終了し、Grafana Loki のみが利用できるようになりました。その少し前からメッセージ監視のアラートの機能が有効になっていますが、皆さんお使いになっているでしょうか。 ここでは、メッセージ監視の通知が、昨日のアラート通知と同様に管理者用(Cluster Monitoring)のAlertmanager と利用者用(User Workload Monitoring)のAlertmanager のどちらから通知されるかを見ていきたいと思います。 Loki のコンポーネントでは Ruler が監視の役割を担いますので、これについて見ていきます。 Ruler Grafana Loki には Ruler と呼ばれるコンポーネントが含まれます。Ruler は設定されたクエリセットを継続的に評価し、その結果に基づいてアクションを起こす責務を持ちます。 grafana.com 具体的には、 AlertingRule と RecordingRule の2つのカスタムリソースを用いてログメッセージを評価し、条件に一致する場合にアラートを通知する事ができます。それぞれのカスタムリソースは、Prometheus の表記と互換性があり、Prometheus を知っている場合は追加の学習コストが低い点が特徴です。 AlertingRule の例 groups: - name: should_fire rules: - alert: HighPercentageError expr: | sum(rate({app="foo", env="production"} |= "error" [5m])) by (job) / sum(rate({app="foo", env="production"}[5m])) by (job) > 0.05 for: 10m labels: severity: page annotations: summary: High request latency - name: credentials_leak rules: - alert: http-credentials-leaked annotations: message: "{{ $labels.job }} is leaking http basic auth credentials." expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)' for: 10m labels: severity: critical メッセージ監視の通知先の AlertManager 昨日、[アラート通知のコントロール( https://rheb.hatenablog.com/entry/2024/12/06/215706 )ということで、以下の3点を確認しました。 利用者はアラート通知を行いたいが、通知先は管理者により管理される 利用者はアラート通知を行いたい、かつ通知先も利用者が管理したい 管理者もカスタムでアラートを追加するため利用者と負荷を分散したい(利用者は通知先の設定を自分で管理しなければならなくなる) 通知先のコントロールを利用者が行うか管理者が行うかについては先日整理したので、本日はメッセージ監視の通知が管理者用の AlertManager か利用者用の AlertManager かを確認していきます。 パターンとしては 1 と 3 を確認します。 利用するアプリとメッセージ監視ルール 一定時間毎に ERROR という文字列を出力するアプリケーションを利用します。特別機能は必要ないので、以下のDeploymentでアプリをデプロします。 cat <<EOF | oc apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: error-logger labels: app: error-logger spec: replicas: 1 selector: matchLabels: app: error-logger template: metadata: labels: app: error-logger spec: containers: - name: error-logger image: busybox command: ["sh", "-c", "while true; do echo ERROR; sleep 1; done"] EOF また、メッセージ監視も ERROR という文字列がある一定以上の割合で出力された場合にアラートを発報するよう設定します。 apiVersion: loki.grafana.com/v1 kind: AlertingRule metadata: name: sample-alert labels: example.jp/system: sample spec: tenantID: "application" groups: - name: SampleError rules: - alert: HighPercentageError expr: | sum(rate({kubernetes_namespace_name="log-sample", kubernetes_pod_name=~".*"} |= "ERROR" [1m])) by (job) / sum(rate({kubernetes_namespace_name="log-sample", kubernetes_pod_name=~".*"}[1m])) by (job) > 0.01 for: 10s labels: severity: critical annotations: summary: This is summary description: This is description アラート監視の設定の有効化 LokiStack はデフォルトではメッセージ監視が有効になっていないために、以下のフィールドを LokiStack に設定します。Namespace セレクターのラベル等は環境ごとに変えてください。 ... spec: ... rules: enabled: true namespaceSelector: matchLabels: example.jp/alert: 'true' selector: matchLabels: example.jp/system: sample ... パターン1: 管理者用の AlertManager への通知 アラート通知の確認で利用したコマンドに、Ruler の設定を表示されるコマンドを追加した以下のコマンドを使って状況を確認していきます。 echo "User: alerts" oc exec -it alertmanager-user-workload-0 -n openshift-user-workload-monitoring -- amtool alert query --alertmanager.url http://localhost:9093 echo "" echo "Cluster: alerts" oc exec -it alertmanager-main-1 -n openshift-monitoring -- amtool alert query --alertmanager.url http://localhost:9093 echo "" echo "User workload: alertmanager.yaml" oc exec -it alertmanager-user-workload-0 -n openshift-user-workload-monitoring -- cat /etc/alertmanager/config_out/alertmanager.env.yaml; echo "" echo "" echo "Cluster: alertmanager.yaml" oc exec -it alertmanager-main-1 -n openshift-monitoring -- cat /etc/alertmanager/config_out/alertmanager.env.yaml; echo "" echo "" echo "Cluster Logging: Ruler" oc exec -it logging-loki-ruler-0 -n openshift-logging -- cat /etc/loki/config/config.yaml | egrep "^ruler:" -A 10; echo "" まずは、管理者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: cluster-monitoring-config namespace: openshift-monitoring data: config.yaml: | enableUserWorkload: true 利用者用の Monitoring の設定はアラート通知については不要です。 この状態で、アラートが発生すると次のようになります。利用者の Monitoring の設定はないため、AlertManager の情報取得はエラーとなります。 Loki の Ruler の設定を見ると https://_web._tcp.alertmanager-operated.openshift-monitoring.svc を参照していることがわかります。管理者用の AlertManager を見ています。この設定が示すように、メッセージ監視のアラート HighPercentageError が管理者用の AlertManager に通知されていることが確認できます。 User: alerts Error from server (NotFound): pods "alertmanager-user-workload-0" not found Cluster: alerts Alertname Starts At Summary State Watchdog 2024-12-07 01:36:52 UTC An alert that should always be firing to certify that Alertmanager is working properly. active UpdateAvailable 2024-12-07 01:38:06 UTC Your upstream update recommendation service recommends you update your cluster. active PrometheusOperatorRejectedResources 2024-12-07 01:42:32 UTC Resources rejected by Prometheus operator active InsightsRecommendationActive 2024-12-07 01:44:33 UTC An Insights recommendation is active for this cluster. active KubeDaemonSetMisScheduled 2024-12-07 01:52:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-07 01:52:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-07 01:52:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetRolloutStuck 2024-12-07 02:07:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-07 02:07:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-07 02:07:49 UTC DaemonSet rollout is stuck. active PrometheusDuplicateTimestamps 2024-12-07 02:37:55 UTC Prometheus is dropping samples with duplicate timestamps. active ClusterNotUpgradeable 2024-12-07 02:38:10 UTC One or more cluster operators have been blocking minor version cluster upgrades for at least an hour. active PrometheusDuplicateTimestamps 2024-12-07 02:38:25 UTC Prometheus is dropping samples with duplicate timestamps. active PodDisruptionBudgetAtLimit 2024-12-07 02:39:38 UTC The pod disruption budget is preventing further disruption to pods. active HighOverallControlPlaneMemory 2024-12-07 05:17:04 UTC Memory utilization across all control plane nodes is high, and could impact responsiveness and stability. active HighPercentageError 2024-12-07 11:55:32 UTC This is summary active User workload: alertmanager.yaml Error from server (NotFound): pods "alertmanager-user-workload-0" not found Cluster: alertmanager.yaml inhibit_rules: - equal: - namespace - alertname source_matchers: - severity = critical target_matchers: - severity =~ warning|info - equal: - namespace - alertname source_matchers: - severity = warning target_matchers: - severity = info receivers: - name: Critical - name: Default slack_configs: - channel: '#openshift-on-kvm' api_url: >- https://hooks.slack.com/services/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 - name: Watchdog route: group_by: - namespace group_interval: 5m group_wait: 30s receiver: Default repeat_interval: 12h routes: - matchers: - alertname = Watchdog receiver: Watchdog - matchers: - severity = critical receiver: Critical Cluster Logging: Ruler ruler: enable_api: true enable_sharding: true alertmanager_url: https://_web._tcp.alertmanager-operated.openshift-monitoring.svc enable_alertmanager_v2: true enable_alertmanager_discovery: true alertmanager_refresh_interval: 1m wal: dir: /tmp/wal truncate_frequency: 60m min_age: 5m パターン3: 利用者用の AlertManager への通知 今度は利用者用の AlertManager へ通知を行います。利用者用のAlertManager の有効化と AlergMangerConfig の設定を有効にします。 管理者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: cluster-monitoring-config namespace: openshift-monitoring data: config.yaml: | enableUserWorkload: true 利用者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: user-workload-monitoring-config namespace: openshift-user-workload-monitoring data: config.yaml: | alertmanager: enabled: true enableAlertmanagerConfig: true この状態で、メッセージ監視を行います。 確認結果は次のとおりとなります。監視の通知が利用者用の AlertManager に届いていることが確認できます。ただし、Ruler の設定が相変わらず管理者用の AlertManager を向いています。何が起きているのでしょうか。 User: alerts Alertname Starts At Summary State HighPercentageError 2024-12-07 12:16:04 UTC This is summary active Cluster: alerts Alertname Starts At Summary State Watchdog 2024-12-07 01:36:52 UTC An alert that should always be firing to certify that Alertmanager is working properly. active UpdateAvailable 2024-12-07 01:38:06 UTC Your upstream update recommendation service recommends you update your cluster. active PrometheusOperatorRejectedResources 2024-12-07 01:42:32 UTC Resources rejected by Prometheus operator active InsightsRecommendationActive 2024-12-07 01:44:33 UTC An Insights recommendation is active for this cluster. active KubeDaemonSetMisScheduled 2024-12-07 01:52:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-07 01:52:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-07 01:52:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetRolloutStuck 2024-12-07 02:07:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-07 02:07:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-07 02:07:49 UTC DaemonSet rollout is stuck. active PrometheusDuplicateTimestamps 2024-12-07 02:37:55 UTC Prometheus is dropping samples with duplicate timestamps. active ClusterNotUpgradeable 2024-12-07 02:38:10 UTC One or more cluster operators have been blocking minor version cluster upgrades for at least an hour. active PrometheusDuplicateTimestamps 2024-12-07 02:38:25 UTC Prometheus is dropping samples with duplicate timestamps. active PodDisruptionBudgetAtLimit 2024-12-07 02:39:38 UTC The pod disruption budget is preventing further disruption to pods. active HighOverallControlPlaneMemory 2024-12-07 05:17:04 UTC Memory utilization across all control plane nodes is high, and could impact responsiveness and stability. active User workload: alertmanager.yaml route: receiver: Default group_by: - namespace routes: - receiver: alert-sample/slack-routing/sample matchers: - namespace="alert-sample" continue: true receivers: - name: Default - name: alert-sample/slack-routing/sample slack_configs: - api_url: https://hooks.slack.com/services/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 channel: '#openshift-on-kvm' templates: [] Cluster: alertmanager.yaml inhibit_rules: - equal: - namespace - alertname source_matchers: - severity = critical target_matchers: - severity =~ warning|info - equal: - namespace - alertname source_matchers: - severity = warning target_matchers: - severity = info receivers: - name: Critical - name: Default slack_configs: - channel: '#openshift-on-kvm' api_url: >- https://hooks.slack.com/services/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 - name: Watchdog route: group_by: - namespace group_interval: 5m group_wait: 30s receiver: Default repeat_interval: 12h routes: - matchers: - alertname = Watchdog receiver: Watchdog - matchers: - severity = critical receiver: Critical Cluster Logging: Ruler ruler: enable_api: true enable_sharding: true alertmanager_url: https://_web._tcp.alertmanager-operated.openshift-monitoring.svc enable_alertmanager_v2: true enable_alertmanager_discovery: true alertmanager_refresh_interval: 1m wal: dir: /tmp/wal truncate_frequency: 60m min_age: 5m 実は、Ruler コンポーネントの設定ファイルは、更に別のファイル /etc/loki/config/runtime-config.yaml によって設定が一部上書きされています。 中身を見ると以下のようになっています。 --- overrides: application: ruler_alertmanager_config: alertmanager_url: https://_web._tcp.alertmanager-operated.openshift-user-workload-monitoring.svc enable_alertmanager_v2: true enable_alertmanager_discovery: true alertmanager_refresh_interval: 1m alertmanager_client: tls_ca_path: /var/run/ca/alertmanager/service-ca.crt tls_server_name: alertmanager-user-workload.openshift-user-workload-monitoring.svc.cluster.local type: Bearer credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token こちらで、通知先の Alertmanager が利用者用となっていることが確認できます。 これで実態と設定の内容が一致しました。 まとめ メッセージ監視の通知がどちらのAlertManager に通知されるか実際の設定と振舞いを確認しました。また実際にPodに設定される内容も確認し、振舞いとあっていることも確認できました。 これでようやく週末を迎えられそうです。
OpenShift のアラート通知の設定 はじめに OpenShift のモニタリングスタック Cluster Monitoring User Workload Monitoring アラート通知のコントロール ケース1 利用者はアラートの設定だけ行いたい ケース2 利用者はアラートの設定も通知先の設定も行いたい ケース3 管理者も多くのアラート通知を行うので、利用者の負荷と分散したい場合 まとめ OpenShift のアラート通知の設定 はじめに この時期にのみ記事を書いている気がしますが、OpenShift Advent Calendar 2024 の 12月5日の記事です。サンタクロースへの手紙をそろそろ書かないと欲しいプレゼントが届かない可能性がでてくる時期になりました。正しく届けないと悲しいクリスマスになるかもしれません。 OpenShift クラスターにおいても、アラートの届け先が大事です。正しく届けないと休みを返上することになるかもしれません。 qiita.com ここでは OpenShift の Cluster Monitoring における AlertManager の利用について整理します。 OpenShift のモニタリングスタック 下の図は Cluster Monitoring 及び User Workload Monitoring の構成を表したものです。赤の点線で optional と書かれている部分は利用者の設定により追加することが可能なコンポーネントになります。 ここで簡単ですが、Cluster Monitoring と User Workload Monitoring が何かを確認しておきます。 Cluster Monitoring 製品ドキュメント の記述をそのままもってきますと以下のように記載があります。 A set of platform monitoring components are installed in the openshift-monitoring project by default during an OpenShift Container Platform installation. This provides monitoring for core cluster components including Kubernetes services. The default monitoring stack also enables remote health monitoring for clusters. These components are illustrated in the Installed by default section in the following diagram. OpenShift インストール時にデフォルトで openshift-monitoring プロジェクトにインストールされるプラットフォームのモニタリングコンポーネントのセット。Kubernetes サービスを含む OpenShift のコアコンポーネントのモニタリングを提供します。デフォルトで用意されているモニタリングスタックはリモートからクラスタの状態をモニタリングする機能も備えています。 User Workload Monitoring 同様に、User Workload Monitoring についてです。 After optionally enabling monitoring for user-defined projects, additional monitoring components are installed in the openshift-user-workload-monitoring project. This provides monitoring for user-defined projects. These components are illustrated in the User section in the following diagram. ユーザ定義プロジェクト用のモニタリングを有効にしたあと、 openshift-user-workload-monitoring プロジェクトに追加のモニタリングコンポーネントがインストールされます。ユーザが定義するプロジェクトのモニタリングを提供します。 文章では触れていませんが、User Workload Monitoring のコンポーネントにも AlertManager が登場します。OpenShift では AlertManager が2つ利用することができます。 ここでは、Cluster Monitoring と User Workload Monitoring の用途を言いやすくするために、管理者用の(Cluster Monitoring)と利用者用の(User Workload Monitoring)という言葉をつかって以降記載していきます。 アラート通知のコントロール 管理者はクラスターの状況を監視しますが、利用者も同様に運用するアプリケーションの監視を行います。アラートの通知を行いたいとか、通知先を個別に管理したいとか要望があるかと思いますが、OpenShift では以下のケースに対応することができます。 利用者はアラート通知を行いたいが、通知先は管理者により管理される 利用者はアラート通知を行いたい、かつ通知先も利用者が管理したい 管理者もカスタムでアラートを追加するため利用者と負荷を分散したい(利用者は通知先の設定を自分で管理しなければならなくなる) このあと、一つ一つ設定と実機による確認をしていきます。実機確認は OpenShift 4.17 を利用し、管理者用の AlertManager の通知先は Slack としています。利用者用の通知先も同じく Slack を利用します。 センシティブな情報については、マスクを掛けますので試す場合は個々の環境に読み替えてください。 ケース1 利用者はアラートの設定だけ行いたい OpenShift では利用者用のMonitoringを有効にすることで、利用者によるアラート設定が行えます。この場合は通常 AlertManager は管理者用のものだけになるため、アラートの通知先は管理者によってのみ管理されます。検証に使うアラートは alert-sample プロジェクトに ExampleUserAlert という名前のアラートを定義して確認します。 管理者用と利用者用の Monitoring の設定は次のようになります。 管理者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: cluster-monitoring-config namespace: openshift-monitoring data: config.yaml: | enableUserWorkload: true 利用者用の Monitoring の設定はアラート通知については不要です。 この設定で、利用者がアラートを設定しアラートが通知されると管理者用の AlertManager に通知が届きます。 雑ですが、以下のスクリプトで状況を確認していきます。 echo "User: alerts" oc exec -it alertmanager-user-workload-0 -n openshift-user-workload-monitoring -- amtool alert query --alertmanager.url http://localhost:9093 echo "Cluster: alerts" oc exec -it alertmanager-main-1 -n openshift-monitoring -- amtool alert query --alertmanager.url http://localhost:9093 echo "User workload: alertmanager.yaml" oc exec -it alertmanager-user-workload-0 -n openshift-user-workload-monitoring -- cat /etc/alertmanager/config_out/alertmanager.env.yaml; echo "" echo "Cluster: alertmanager.yaml" oc exec -it alertmanager-main-1 -n openshift-monitoring -- cat /etc/alertmanager/config_out/alertmanager.env.yaml; echo "" 確認結果は以下の通りとなります。管理者用の AlertManager しかないこともありますが、管理者用の AlertManager に通知が上がっていることが確認できます。そして、通知先は管理者が設定したSlackのみが指定されています。 User: alerts Error from server (NotFound): pods "alertmanager-user-workload-0" not found Cluster: alerts Alertname Starts At Summary State Watchdog 2024-12-05 23:06:52 UTC An alert that should always be firing to certify that Alertmanager is working properly. active UpdateAvailable 2024-12-05 23:07:36 UTC Your upstream update recommendation service recommends you update your cluster. active PrometheusOperatorRejectedResources 2024-12-05 23:12:32 UTC Resources rejected by Prometheus operator active InsightsRecommendationActive 2024-12-05 23:15:03 UTC An Insights recommendation is active for this cluster. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active ClusterNotUpgradeable 2024-12-06 00:07:40 UTC One or more cluster operators have been blocking minor version cluster upgrades for at least an hour. active PrometheusDuplicateTimestamps 2024-12-06 00:07:55 UTC Prometheus is dropping samples with duplicate timestamps. active PrometheusDuplicateTimestamps 2024-12-06 00:07:55 UTC Prometheus is dropping samples with duplicate timestamps. active PodDisruptionBudgetAtLimit 2024-12-06 00:09:08 UTC The pod disruption budget is preventing further disruption to pods. active ExampleUserAlert 2024-12-06 12:19:23 UTC This is sample summary active User workload: alertmanager.yaml Error from server (NotFound): pods "alertmanager-user-workload-0" not found Cluster: alertmanager.yaml inhibit_rules: - equal: - namespace - alertname source_matchers: - severity = critical target_matchers: - severity =~ warning|info - equal: - namespace - alertname source_matchers: - severity = warning target_matchers: - severity = info receivers: - name: Critical - name: Default slack_configs: - channel: '#openshift-on-kvm' api_url: >- https://hooks.slack.com/services/XXXXXX - name: Watchdog route: group_by: - namespace group_interval: 5m group_wait: 30s receiver: Default repeat_interval: 12h routes: - matchers: - alertname = Watchdog receiver: Watchdog - matchers: - severity = critical receiver: Critical ケース2 利用者はアラートの設定も通知先の設定も行いたい 利用者がアラートの通知先を設定するには AlertmanagerConfig リソースを設定しその設定を管理者用の AlertManager に設定する必要があります。利用者が作成する AlertManagerConfig リソースは、Namespace スコープのリソースとなるため、Namespace/Project ごとに設定が必要となります。 設定は次のとおりとなります。 管理者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: cluster-monitoring-config namespace: openshift-monitoring data: config.yaml: | enableUserWorkload: true alertmanagerMain: enableUserAlertmanagerConfig: true 利用者用の Monitoring の設定はアラート通知については不要です。 この設定を実施した状態で、 AlertmanagerConfig を設定します。通知先である Slack の URL は webhook Secret の url Key として定義しています。 apiVersion: monitoring.coreos.com/v1beta1 kind: AlertmanagerConfig metadata: name: slack-routing spec: route: receiver: sample receivers: - name: sample slackConfigs: - channel: '#openshift-on-kvm' apiURL: name: webhook key: url サンプルのアラートを設定してしばらくたったあとの確認結果は次のとおりとなります。アラートは管理者用の AlertManager に通知され、かつ、alert-sample プロジェクト用の通知先が設定されているのが確認できます。 User: alerts Error from server (NotFound): pods "alertmanager-user-workload-0" not found Cluster: alerts Alertname Starts At Summary State Watchdog 2024-12-05 23:06:52 UTC An alert that should always be firing to certify that Alertmanager is working properly. active UpdateAvailable 2024-12-05 23:07:36 UTC Your upstream update recommendation service recommends you update your cluster. active PrometheusOperatorRejectedResources 2024-12-05 23:12:32 UTC Resources rejected by Prometheus operator active InsightsRecommendationActive 2024-12-05 23:15:03 UTC An Insights recommendation is active for this cluster. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active ClusterNotUpgradeable 2024-12-06 00:07:40 UTC One or more cluster operators have been blocking minor version cluster upgrades for at least an hour. active PrometheusDuplicateTimestamps 2024-12-06 00:07:55 UTC Prometheus is dropping samples with duplicate timestamps. active PrometheusDuplicateTimestamps 2024-12-06 00:07:55 UTC Prometheus is dropping samples with duplicate timestamps. active PodDisruptionBudgetAtLimit 2024-12-06 00:09:08 UTC The pod disruption budget is preventing further disruption to pods. active ExampleUserAlert 2024-12-06 12:19:23 UTC This is sample summary active User workload: alertmanager.yaml Error from server (NotFound): pods "alertmanager-user-workload-0" not found Cluster: alertmanager.yaml route: receiver: Default group_by: - namespace routes: - receiver: alert-sample/slack-routing/sample matchers: - namespace="alert-sample" continue: true - receiver: Watchdog matchers: - alertname = Watchdog - receiver: Critical matchers: - severity = critical group_wait: 30s group_interval: 5m repeat_interval: 12h inhibit_rules: - target_matchers: - severity =~ warning|info source_matchers: - severity = critical equal: - namespace - alertname - target_matchers: - severity = info source_matchers: - severity = warning equal: - namespace - alertname receivers: - name: Critical - name: Default slack_configs: - api_url: https://hooks.slack.com/services/XXXXX channel: '#openshift-on-kvm' - name: Watchdog - name: alert-sample/slack-routing/sample slack_configs: - api_url: https://hooks.slack.com/services/YYYYYY channel: '#openshift-on-kvm' templates: [] AlertManager のレシーバーの名前が alert-sample/slack-routing/sample と長いですが、Namespace が alert-sample の場合はこちらに通知されます。 ケース3 管理者も多くのアラート通知を行うので、利用者の負荷と分散したい場合 こちらは利用者の要望ではなく、管理者側の要望で、利用者のアラート通知と管理者のアラート通知の負荷を分散するために、個別に AlertManager を利用することを考えます。 設定は次のとおりとなり、利用者用の Monitoring に Alertmanager の有効化と、AlertmanagerConfig の有効化が設定されます。 管理者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: cluster-monitoring-config namespace: openshift-monitoring data: config.yaml: | enableUserWorkload: true 利用者用の Monitoring の設定 apiVersion: v1 kind: ConfigMap metadata: name: user-workload-monitoring-config namespace: openshift-user-workload-monitoring data: config.yaml: | alertmanager: enabled: true enableAlertmanagerConfig: true この設定を行った状態で、AlertmanagerConfig を設定します。設定内容は前回と同様に次のとおりです apiVersion: monitoring.coreos.com/v1beta1 kind: AlertmanagerConfig metadata: name: slack-routing spec: route: receiver: sample receivers: - name: sample slackConfigs: - channel: '#openshift-on-kvm' apiURL: name: webhook key: url サンプルのアラートを設定してしばらくたったあとの確認結果は次のとおりとなります。アラートは利用者用の AlertManager に通知され、かつ、alert-sample プロジェクト用の通知先も利用者用のAlertManager に設定されているのが確認できます。 User: alerts Alertname Starts At Summary State ExampleUserAlert 2024-12-06 12:47:43 UTC This is sample summary active Cluster: alerts Alertname Starts At Summary State Watchdog 2024-12-05 23:06:52 UTC An alert that should always be firing to certify that Alertmanager is working properly. active UpdateAvailable 2024-12-05 23:07:36 UTC Your upstream update recommendation service recommends you update your cluster. active PrometheusOperatorRejectedResources 2024-12-05 23:12:32 UTC Resources rejected by Prometheus operator active InsightsRecommendationActive 2024-12-05 23:15:03 UTC An Insights recommendation is active for this cluster. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetMisScheduled 2024-12-05 23:22:49 UTC DaemonSet pods are misscheduled. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active KubeDaemonSetRolloutStuck 2024-12-05 23:37:49 UTC DaemonSet rollout is stuck. active ClusterNotUpgradeable 2024-12-06 00:07:40 UTC One or more cluster operators have been blocking minor version cluster upgrades for at least an hour. active PrometheusDuplicateTimestamps 2024-12-06 00:07:55 UTC Prometheus is dropping samples with duplicate timestamps. active PrometheusDuplicateTimestamps 2024-12-06 00:07:55 UTC Prometheus is dropping samples with duplicate timestamps. active PodDisruptionBudgetAtLimit 2024-12-06 00:09:08 UTC The pod disruption budget is preventing further disruption to pods. active User workload: alertmanager.yaml route: receiver: Default group_by: - namespace routes: - receiver: alert-sample/slack-routing/sample matchers: - namespace="alert-sample" continue: true receivers: - name: Default - name: alert-sample/slack-routing/sample slack_configs: - api_url: https://hooks.slack.com/services/YYYYY channel: '#openshift-on-kvm' templates: [] Cluster: alertmanager.yaml inhibit_rules: - equal: - namespace - alertname source_matchers: - severity = critical target_matchers: - severity =~ warning|info - equal: - namespace - alertname source_matchers: - severity = warning target_matchers: - severity = info receivers: - name: Critical - name: Default slack_configs: - channel: '#openshift-on-kvm' api_url: >- https://hooks.slack.com/services/XXXXX - name: Watchdog route: group_by: - namespace group_interval: 5m group_wait: 30s receiver: Default repeat_interval: 12h routes: - matchers: - alertname = Watchdog receiver: Watchdog - matchers: - severity = critical receiver: Critical まとめ アラートの通知に関して、管理者用と利用者用の設定を変更することで、利用者に通知先の設定を移譲したりと様々な設定ができることが確認できました。これで安心してアラート設計が行えると思います。 では、最後に ChatGPT になぞかけをひとつ作ってもらいましたので、最後の締めとして残します。 サンタクロースへの手紙とかけて、アラートの通知先と解きます。 その心は? どちらも「届ける相手」が重要です! 🎅📩 おつかれさまでした。
Red Hat で Ansible のソリューションアーキテクトをしている中島でございます。 本エントリーは Ansible Advent Calendar 2024 の6日目の記事となります。 Ansible Advent Calendar 2024 にはAnsible 関する様々なTIPSやナレッジが投稿されておりますの、Ansible を触っている方はご一読いただくと、自動化のステップアップのきっかけを得られるかもしれません。 さて、現在の Red Hat Ansible Automation Platform(以下AAP) は Playbook を実行するためにコンテナ環境(Execution Environment: 以下EE)を使っています。EEを使うことで複雑化したモジュールの依存関係をOS本体とは切り離し、「開発環境では動いたのに!」という状況を極力抑えることができます。そして、EEを使ったPlaybook開発のための仕組みとして、 ansible-navigator コマンドがあります。 ansible-navigator は ansible-playbook コマンドと表面上は概ね同じですが、大きく違うのがPlaybookを実行するためにEEを利用します。開発では ansible-navigator を使い、本番ではAAPを利用する。そしてそのどちらにも同じEEを使用することで、開発と本番の差異をなくし、Playbookの実行環境に起因するトラブルを削減することができます。 ansible-navigator を使う場合、Playbook の実行はEEという「コンテナの中」で実行され、自分が操作している開発環境のOS上の設定とは独立して動きます。これは環境の独立性を担保する意味では便利な半面、別の部分では不便な部分も出てきます。それが情報(変数)の受け渡しです。 今回は、 ansible-navigator を使って情報を受け渡し、Playbook開発の効率を高める方法について紹介します(AAP上では簡単に設定して利用できる各種変数などを、 ansible-navigator を使った時にどうするか、という話だと思ってください)。 ここからが本題です。今回は AWS を例にサンプルを見ながら紹介します。 以下のようなPlaybookを準備します。これはAWS EC2上のインスタンス情報を取得するPlaybookです。 --- - hosts: all gather_facts: false tasks: - name: Gather information about all instances amazon.aws.ec2_instance_info: register: ret - debug: var=ret これをAAPで使う場合は、「AWS用の暗号化された認証オブジェクト」を作成してジョブにアタッチするだけで安全に利用できますが・・・、コマンドラインで使う場合には以下のようにします。 このAWSモジュール用に必要な環境変数をセットしておきます。 export AWS_ACCESS_KEY=xxx export AWS_SECRET_KEY=yyy export AWS_REGION=ap-northeast-1 ではまず、 ansible-playbook コマンドで実行してみます。インベントリーファイルを準備していないので、 -i localhost, -c local オプションでコマンドラインの中で接続先と接続方法を指定しています。 $ ansible-playbook -i localhost, -c local playbook.yaml PLAY [all] ******************************************************************** TASK [Gather information about all instances] ********************************* ok: [localhost] TASK [debug] ****************************************************************** ok: [localhost] => { "ret": { "changed": false, "failed": false, "instances": [ (省略) } } PLAY RECAP ******************************************************************** localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 問題なく実行できています。では、同じ条件で ansible-navigator を使ってみます。 $ ansible-navigator run playbook.yaml -i localhost, -c local -m stdout -e 'ansible_python_interpreter=/usr/bin/python' PLAY [all] ********************************************************************* TASK [Gather information about all instances] ********************************** fatal: [localhost]: FAILED! => {"changed": false, "msg": "The amazon.aws.ec2_instance_info module requires a region and none was found in configuration, environment variables or module parameters"} PLAY RECAP ********************************************************************* localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 Please review the log for errors. Note: 今回の利用しているEEのイメージ registry.redhat.io/ansible-automation-platform-25/ee-supported-rhel8 は -c local で接続すると、OS管理用の /usr/libexec/platform-python が使用されてしまうため、明示的に /usr/bin/python を使うように指定しています。 認証情報が参照できないため接続エラーがおきているのがわかります。 では、 ansible-navigator に認証情報を渡してみます。一番簡単なのは --senv オプションで環境変数として渡す方法です。 $ ansible-navigator run playbook.yaml -i localhost, -c local -m stdout -e 'ansible_python_interpreter=/usr/bin/python' --senv 'AWS_ACCESS_KEY=xxx' --senv 'AWS_SECRET_KEY=yyy' --senv 'AWS_REGION=ap-northeast-1' (省略) PLAY RECAP ******************************************************************** localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 うまく動きました。別の方法として、現行シェルの変数を渡す --penv というオプションもあります。 $ ansible-navigator run playbook.yaml -i localhost, -c local -m stdout -e 'ansible_python_interpreter=/usr/bin/python' --penv AWS_ACCESS_KEY --penv AWS_SECRET_KEY --penv AWS_REGION (省略) PLAY RECAP ******************************************************************** localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 こちらもうまく動いています。 -e は extra_vars として ansible の変数として渡され、 --penv --senv は環境変数として渡されます。似て非なるものなので、どちらで渡したいのかをモジュールの仕様を確認し、違いを意識して利用できるとトラブルを減らすことができます。 ansible-playbook から ansible-navigator に移行すると、環境のベースがコンテナに移ることで、Ansible での接続や認証等の基本的な部分で引っかかることがよくあります。特に認証周りは最初のつまづきポイントです。もし、 ansible-navigator での開発で、認証周りでうまくいかないことがあれば、今回紹介したコマンドからEEへの情報の受け渡しについて確認してみてください。
みなさん今日もメリークリスマス。昨日に引き続きRed Hatのさいとうです。 Ansible Advent Calendar 2024 の、12月5日の記事をお届けします。 ansible.posix collection version 2.0.0 をリリースしました 僕はサポートチームに所属していますが、表の仕事の障害解析の合間にアップストリームのメンテナの仕事もしています。こういう境遇の人をRed Hatではよく見かけます。 Red Hatは、一般社会的には謎に包まれているとはいえオープンソースソフトウェアカンパニーですから、所属している部門や、就いている職種にかかわらず、アップストリームへの貢献が自由として認められています。日常業務とアップストリームの仕事をどのようにバランスするかという点については、ある程度は当人にまかされているとはいえ、ちゃんと表の仕事もしないといけません。僕の場合は、表の仕事がAnsible Automation Platformの障害解析、アップストリームのメンテナのほうが裏の仕事という感じです。 そんな裏の仕事で、さきほど(2024年12月5日)、Ansible Collectionの1つである、 ansible.posixのバージョン2.0.0 をリリースしました。 今日は、 昨日の投稿 で、アップスチームへのコードコミットにチャレンジしようと思ってくれたあなたのために、知っておいてもきっと損はしないAnsible Collectionのリリースプロセスについてご紹介しようと思います。 Ansible Collectionのリリースタイミング Ansible Collectionのリリースタイミングは、基本的にメンテナの判断にまかされています。Ansible Coreとリポジトリが分けられたのも、メンテナの都合で自由にリリースできるようにしようという配慮からです。そのような背景から、数多くあるAnsible Collectionには、それぞれ独自のリリースポリシーがあります。ここから先は、ansible.posixコレクションの場合のお話です。 ansible.posixコレクションの場合は、現状だと年に1回や半年にに1回といった定期的なリリースは行っておらず、いい感じにマージされたPull Requestが溜まってきたタイミングで、アクティブなメンテナ間で話しあってリリース時期を決めています。決定したら、リリース日とバージョンを含めて以下のIssueで広く伝えられます。 Release plan #149 希に、不適切なバージョニングなどの理由で、Ansible Communityから修正したリリースを求められる場合もあります。この場合は緊急リリースとなります。僕は2回ほど経験しました。 バージョニング バージョンについては、昔はフンイキで決めていた(当時もバージョニングの理由はそれなりにありました)のですが、現在では以下のガイドラインに従っています。 Versioning and deprecation Semantic Versioning 2.0.0 これに従わない異端なAnsible Collectionは、 Ansible community package から除外されて、広義のAnsible(※1)には収録されなくなります。どの世界でも異端児は住みにくい世の中ですが、最終的にこのようなガイドラインがあることで、メンテナの仕事がやりやすくなり、またAnsible Communityによるガバナンスが効くことで品質の高いリリースに繋がり、最終的に利用者がハッピーになっているように感じます。 いま、Ansible Collectionを使っていてあまり幸せじゃないひとがいたら、このガイドラインがなければもっと幸せじゃなかったはずです。いや本当に。 ※1:狭義のAnsibleはAnsible Coreです リリース前日までの準備 リリース日とバージョンが決まれば、あとはそれにしたがってプロセスを淡々と進めることになります。 メジャーリリースの場合 : 昨日の記事で紹介 した breaking_changes と removed_features をできるだけ詰め込まないといけませんから、マージ前のPull Requestのオーナーに必用な修正をお願いしたり、レビュアのchange requestに反応がないけど重要なPRをメンテナが強制的に修正してマージしたりして進めていきます。間に合わなければ、次のメジャーバージョンアップまで積み残すことになるからです。 マイナーリリースの場合 : マイナーバージョンアップはゆるゆると準備できます。よほど重要だったり深刻だったりする bugfixes や minor_changes 以外は積み残しても、次回のマイナーリリースはいつでもできます。 リリース前日 リリースを担当するメンテナは、以下の流れでリリースコミットを作成します。以下は僕の作業手順ですが、きっともっとかっこいい方法があるはず。 1. changelog fragmentsからCHANGELOG.rstを生成するための antsibull-changelog コマンドをインストールする antsibull-changelog はchangelog fragmentsからCHANGELOGを生成してくれるイカしたやつです。 % pip install --user antsibull-changelog 2. ローカルにリリース用のPull Requestを作成するための作業用ブランチを作成する アップストリームのansible.posixをforkしてチェックアウトし、リリース用のローカルブランチ(release_2.0.0)を作ります。 % git checkout -b release_2.0.0 3. galaxy.ymlのversionをリリースバージョンに変更する Ansible Collectionのバージョンは、リポジトリのトップレベルディレクトリにある galaxy.yml で定義されています。これをリリースするバージョンに変更します。 --- namespace : ansible name : posix version : 2.0.0 # <= ここ readme : README.md authors : - Ansible (github.com/ansible) description : Ansible Collection targeting POSIX and POSIX-ish platforms. license_file : COPYING tags : [ posix, networking, shell, unix ] dependencies : {} repository : https://github.com/ansible-collections/ansible.posix documentation : https://docs.ansible.com/ansible/latest/collections/ansible/posix/ homepage : https://github.com/ansible-collections/ansible.posix issues : https://github.com/ansible-collections/ansible.posix 4. リリースコミット用のchangelog fragmentファイルを作成する antsibull-changelogコマンドで生成される CHANGELOG.rst と changelogs/changelog.yaml に、これからリリースする2.0.0のエントリを追加するために、fragmentファイル(changelogs/fragments/2.0.0.yml)を作成します。内容は以下のような感じのリリースの概要説明文です。 release_summary : |- This is the major release of the ``ansible.posix`` collection. This changelog contains all changes to the modules and plugins in this collection that have been added after the release of ``ansible.posix`` 1.6.2 5. CHANGELOGを生成する antsibull-changelog コマンドを実行します。 % antsibull-changelog release --reload-plugins このコマンドは、 changelogs/fragments/ ディレクトリ配下にある全てのfragmentファイルを削除して、以下の2つのファイルを生成します。 CHANGELOG.rst changelogs/changelog.yaml これが、このリリースの CHANGELOG となって、みなさんに見える形になるわけです。 CHANGELOGの生成時に changelogs/fragments/ ディレクトリ以下にあるfragmentファイル群を削除してくれるので、リポジトリとしてはchangelog fragmentsが綺麗な状態で次のリリースを迎えられます(※2)。なかなか便利でよくできてる。 ※2:このクリーニングの設定は changelogs/config.yml で keep_fragments: false となっていれば有効化されています。 6. リリースコミットを作ってpush! リリースコミットを作って、Upstreamからforkしたoriginにpushします。 % git remote -v origin git@github.com:saito-hideki/ansible.posix.git (fetch) origin git@github.com:saito-hideki/ansible.posix.git (push) upstream git@github.com:ansible-collections/ansible.posix.git (fetch) upstream git@github.com:ansible-collections/ansible.posix.git (push) % git commit -a -m "Release 2.0.0 commit" --signoff % git push origin release_2.0.0 7. リリースコミットのPull Requestを作成する pushしたら、 Draft Pull Request を作って、自動テストがひと回りして成功するのを待ちます。この待ち時間は結構気持ち的に落ち着かない。 無事に自動テストが通ったら、 Ready for review をポチッとして、僕以外のアクティブなメンテナを指定してReview Requestを送ります。2人以上のApproveが貰えたらマージプロセスに入ります(俺的ルール)。 8. リリースコミットのマージ ansible.posixコレクションのマージプロセスは、特にややこしいことはなく、メンテナが mergeit ラベルをPull Requestに付与することで、botが発動してマージプロセスを実行してくれます。ここでも自動テストが走ります。ここが一番気持ち的に長い。ときどきコケて絶望します。 9. Upstream側にtagを切る マージされたらUpstream側にtagを切ります。完了までもう少し。ここから先は、もう理不尽にコケるところはないので気楽な作業です。 $ git checkout main $ git pull $ git tag -a 2.0.0 -m "Release 2.0.0" $ git push upstream 2.0.0 10. リリースを作成する リリースアーカイブをGitHubのダッシュボードから作成します。 https://github.com/ansible-collections/ansible.posix/releases/new Press `Draft a new release` Release title: Release 2.0.0 Describe for release: ~~~ ansible.posix version 2.0.0: * [CHANGELOG](https://github.com/ansible-collections/ansible.posix/blob/2.0.0/CHANGELOG.rst) for all changes ~~~ リリースを作成した時点で、 Community Galaxy にリリースが反映されます。この時点から、一般ユーザが ansible-galaxy collection install ansible.posix コマンドでインストールできるようになります。 ansible.posixはRed Hatが公式にサポートしているコレクションですから、 Red Hat Hybrid Cloud Console でもアーカイブが提供されています。こちらの反映時には厳格なテストが行われるので、即反映とはなりません。長くて数日かかります。Red Hatさんちゃんとしてる。 11. Ansible Communityにリリースアナウンス もうちょっとだ。 Matrix にある、Ansible CommunityのAnsible Socialチャンネルで、newsbot宛てにリリースを伝えます。 @newsbot: ansible.posix 2.0.0 has been released. This release includes two break fixes for options in the firewalld module. Additionally, please note that the Skippy plugin has been removed. You can see more details in changelog. これで、Ansible Communityからのnews letterにリリースが掲載されます。 12. リリース完了! ansible.posixリポジトリの Release plan #149 でもリリースをアナウンスします。 リリース完了! 世界のどこかにいるAndresson007とmaxamillionの2人に感謝。いつもレビューありがとう! :) まとめ これが僕がメンテナになってから、有識者に聞いたりドキュメントをかき集めたAnsible Collectionのリリースプロセスの流れです。 メンテナガイドみたいな、まとまったドキュメントがあると思ってたんだけどなぁ.....なってみたら、この世にそんな都合の良いものはなかったっていうよくある話でした。community.generalは、もっとかっこいい方法を持ってるらしいと風の噂に聞いたので、今度聞きに行ってみようと思います。 ドキュメントがなければ、自分で作ればいいっていうのは、 昨日のお話 の、いっそ自分でコードを修正しちゃったほうが速いっていうのと通じますね。あれ通じないかな。あったほうがいいよなやっぱり。 それではみなさん、今日もHappy Automation!
Red Hatの小島です。 クラウドベンダーがサポートする従量課金制RHEL(オンデマンドのRHELインスタンス)では、Red Hat Update Infrastructure (RHUI) というクラウド環境専用のRHELリポジトリを使って、RHELパッケージのダウンロード/インストール/アップデートなどができるように予め設定されています。さらに、AWS/Azure/Google Cloudの従量課金制RHELでは、Red Hat Subscription Management (RHSM) ではなくRHUIを利用して、RHEL7以降のRHELやRHEL with SAP HANAをインプレースアップグレードすることができるようになっています。本記事ではRHUIを参照したRHELのインプレースアップグレードの概要について紹介します。 ちなみに、本記事で言及しているRed Hatのナレッジベースについては、Red Hatのサブスクリプションを持たないAWS/Azure/Google CloudのRHELユーザーでも参照できるようにしている仕組みがあります。この仕組みを利用することで、インプレースアップグレードについてRed Hatのナレッジベースで調べながら、不明点をAWS/Microsoft/GoogleのRHELサポート窓口に問い合わせることができます。詳細については本記事末尾の参考情報に記載してある各Webページをご参照ください。 サポート対象となるインプレースアップグレードパス インプレースアップグレードの前準備 AWSの場合 Azureの場合 Google Cloudの場合 インプレースアップグレード前のレポートの確認 インプレースアップグレードの実行 参考情報 leappを利用したRHELのインプレースアップグレードガイド AWS/Azure/Google CloudのRHELユーザーのRed Hatナレッジベースへのアクセスガイド AWS/AzureでのRHEL EUSの利用ガイド サポート対象となるインプレースアップグレードパス サポート対象となるインプレースアップグレードパスを確認します。RHEL7は最新マイナーリリースのRHEL7.9、RHEL8はRHEL8.8かRHEL8.10をアップグレード対象にすることができます。RHEL7やRHEL8を使っている場合、 yum update や dnf update コマンドを利用して、RHEL7.9やRHEL8.10の最新パッケージに予めアップデートしておく必要があります。AWSやAzureのMarketplaceから作成したRHEL8のEUS(RHEL8.8やRHEL9.4など特定のマイナーリリースの延長サポートアドオン)を利用している場合、RHEL8.8 EUSの最新パッケージにアップデートしてください。2024年12月時点において、Google CloudではRHELのEUSを利用できません。 RHEL7からRHEL9へのインプレースアップグレードを直接実行することはできません。RHEL7をRHEL9にアップグレードしたい場合、RHEL7からRHEL8へ、RHEL8からRHEL9へとアップグレードする必要があります。なお、RHEL7は延長サポートのアドオン(ELS)が提供されていますが、ELSの利用有無に関係なく、RHEL7からRHEL8へのインプレースアップグレードを実行できます。 access.redhat.com インプレースアップグレードの前準備 RHELの特定のパッケージのバージョンをロックするために yum-versionlock プラグインを利用している場合、leappによるインプレースアップグレード実行においては無効化する必要がありますので、yumコマンドで無効化しておきます。 $ sudo yum versionlock clear access.redhat.com RHUIを使用してインプレースアップグレードを実行するために、必要なRHUIリポジトリを有効にしてパッケージをインストールします。AWS/Azure/Google Cloudにおいて、それぞれ手順が異なります。 AWSの場合 RHEL7からRHEL8へのインプレースアップグレードの場合は、 rhui-client-config-server-7 と rhel-7-server-rhui-extras-rpms リポジトリ参照を有効化して、leapp関連のパッケージをインストールします。 $ sudo yum-config-manager --enable rhui-client-config-server-7 $ sudo yum-config-manager --enable rhel-7-server-rhui-extras-rpms $ sudo yum -y install rh-amazon-rhui-client leapp-rhui-aws RHEL8からRHEL9へのインプレースアップグレードの場合は、 rhui-client-config-server-8 リポジトリ参照を有効化して、leapp関連のパッケージをインストールします。 $ sudo dnf config-manager --set-enabled rhui-client-config-server-8 $ sudo dnf -y install leapp-rhui-aws Azureの場合 RHEL7からRHEL8へのインプレースアップグレードの場合は、 rhui-microsoft-azure-rhel7 と rhui-rhel-7-server-rhui-extras-rpms リポジトリ参照を有効化して、leapp関連のパッケージをインストールします。 $ sudo yum-config-manager --enable rhui-microsoft-azure-rhel7 $ sudo yum-config-manager --enable rhui-rhel-7-server-rhui-extras-rpms $ sudo yum -y install rhui-azure-rhel7 leapp-rhui-azure RHEL8からRHEL9へのインプレースアップグレードの場合は、 rhui-microsoft-azure-rhel8 リポジトリ参照を有効化して、leapp関連のパッケージをインストールします。 $ sudo dnf config-manager --set-enabled rhui-microsoft-azure-rhel8 $ sudo dnf -y install rhui-azure-rhel8 leapp-rhui-azure Google Cloudの場合 次のナレッジベースを参照して、各システムに対応するtarballをダウンロードしてその中のRPMパッケージをインストールします。これにより、leappによるインプレースアップグレードの実行中に、必要となるRHEL8やRHEL9パッケージをダウンロードするためのリポジトリ情報がインストールされます。 access.redhat.com RHEL with SAP HANAを利用していないRHEL7からRHEL8へのインプレースアップグレードの場合は、上記のナレッジベースから leapp-rhui-google-X-rhel7.tar.gz (Xは変数です)をダウンロードしてRPMパッケージをインストールします。 $ tar xf leapp-rhui-google-v4-rhel7.tar.gz $ sudo yum -y localinstall leapp-rhui-google-1.0.0-6.el7.noarch.rpm $ rpm -ql leapp-rhui-google ...<snip>... /usr/share/leapp-repository/repositories/system_upgrade/common/files/rhui/google/leapp-google.repo RHEL with SAP HANAを利用していないRHEL8からRHEL9へのインプレースアップグレードの場合は、上記のナレッジベースから leapp-rhui-google-X-rhel8.tar.gz (Xは変数です)をダウンロードしてRPMパッケージをインストールします。 $ tar xf leapp-rhui-google-v4-rhel8.tar.gz $ sudo dnf -y install leapp-rhui-google-1.0.0-6.el8.noarch.rpm $ rpm -ql leapp-rhui-google ...<snip>... /usr/share/leapp-repository/repositories/system_upgrade/common/files/rhui/google/leapp-google.repo 上記の手順を実施してAWS/Azure/Google Cloudでの必要なRHUIリポジトリの有効化とパッケージインストールをした後は、 leapp-upgrade パッケージをインストールして、システムの全てのパッケージを最新版にして再起動します。これらはAWS/Azure/Google CloudのRHEL7とRHEL8で、共通のコマンドとして実行できます。インプレースアップグレード実行時のエラーを回避するために、全パッケージを最新版に更新することを忘れないようにしてください。 $ sudo yum -y install leapp-upgrade $ sudo yum -y update $ sudo reboot インプレースアップグレード前のレポートの確認 RHEL7とRHEL8では leapp preupgrade コマンドを実行して、アップグレード実行時の潜在的な問題を特定できます。下記はRHEL7.9システムで、RHEL8.10へのアップグレードを実行する際に特定された問題をレポートするコマンドの実行例です。 $ sudo leapp preupgrade --no-rhsm --target 8.10 ...<snip>... Debug output written to /var/log/leapp/leapp-preupgrade.log ============================================================ REPORT OVERVIEW ============================================================ Upgrade has been inhibited due to the following problems: 1. Possible problems with remote login using root account 2. Missing required answers in the answer file HIGH and MEDIUM severity reports: 1. Difference in Python versions and support in RHEL 8 2. Detected custom leapp actors or files. Reports summary: Errors: 0 Inhibitors: 2 HIGH severity reports: 2 MEDIUM severity reports: 0 LOW severity reports: 4 INFO severity reports: 3 Before continuing, review the full report below for details about discovered problems and possible remediation instructions: A report has been generated at /var/log/leapp/leapp-report.txt A report has been generated at /var/log/leapp/leapp-report.json ============================================================ END OF REPORT OVERVIEW ============================================================ Answerfile has been generated at /var/log/leapp/answerfile RHUIを利用してアップグレードを実行するので、 --no-rhsm オプションでRHSMを利用しないように指定します。このオプションを指定しないと、RHSMで登録されていないといったエラーが出力されてアップグレードが実行できません。 --target オプションでアップグレードターゲットのRHELのリリース番号を指定します。例えば、RHEL7.9からRHEL8.10にアップグレードする場合は --target 8.10 を、RHEL8.10からRHEL9.4にアップグレードする場合は --target 9.4 を指定します。AWSとAzureの従量課金制のRHELではEUSを利用できますので、EUSを利用したい場合はアップグレード完了後にEUSのリポジトリ参照を有効化するようにします。EUSリポジトリの有効化手順については、本記事末尾の参考情報に記載してある各Webページをご参照ください。 上記コマンドの実行結果にあるように、レポートは /var/log/leapp/leapp-report.{txt,json} ファイルに出力されます。ここで見つかった問題を修正していきます。最低限 Errors と Inhibitors で分類された問題を修正しないと、アップグレードを実行できないようになっています。レポートされた問題には解決のヒントとなるレッドハットのナレッジベースのURLが記載されていることが多いので、それらを適宜参照しながら修正していきます。 下記はレポートされた問題の一部を引用した例です。報告された問題の中には下記の例のように「 python コマンドがRHEL8ではありません」といったものもあるので、アップグレード後の修正も適宜考慮する必要があります。 $ sudo cat /var/log/leapp/leapp-report.txt Risk Factor: high (inhibitor) Title: Possible problems with remote login using root account Summary: OpenSSH configuration file does not explicitly state the option PermitRootLogin in sshd_config file, which will default in RHEL8 to "prohibit-password". Remediation: [hint] If you depend on remote root logins using passwords, consider setting up a different user for remote administration or adding "PermitRootLogin yes" to sshd_config. If this change is ok for you, add explicit "PermitRootLogin prohibit-password" to your sshd_config to ignore this inhibitor Key: 3d21e8cc9e1c09dc60429de7716165787e99515f ---------------------------------------- Risk Factor: high (inhibitor) Title: Missing required answers in the answer file Summary: One or more sections in answerfile are missing user choices: remove_pam_pkcs11_module_check.confirm For more information consult https://red.ht/leapp-dialogs. Related links: - Leapp upgrade fail with error "Inhibitor: Missing required answers in the answer file.": https://access.redhat.com/solutions/7035321 Remediation: [hint] Please register user choices with leapp answer cli command or by manually editing the answerfile. [command] leapp answer --section remove_pam_pkcs11_module_check.confirm=True Key: d35f6c6b1b1fa6924ef442e3670d90fa92f0d54b ---------------------------------------- Risk Factor: high Title: Difference in Python versions and support in RHEL 8 Summary: In RHEL 8, there is no 'python' command. Python 3 (backward incompatible) is the primary Python version and Python 2 is available with limited support and limited set of packages. If you no longer require Python 2 packages following the upgrade, please remove them. Read more here: https://red.ht/rhel-8-python Related links: - Difference in Python versions and support in RHEL 8: https://red.ht/rhel-8-python Remediation: [hint] Please run "alternatives --set python /usr/bin/python3" after upgrade Key: 0c98585b1d8d252eb540bf61560094f3495351f5 ---------------------------------------- ...<snip>... このレポートはWebコンソールでも確認できます。RHEL7, RHEL8, RHEL9ではCockpitというWebベースのコンソールを利用してシステム管理が可能です。このCockpitのプラグインを利用してレポートを表示します。そのために、 cockpit-leapp パッケージをインストールします。Webサービスを実行する cockpit.socket サービスを実行していない場合は、systemctlコマンドで有効にして起動します。 $ sudo yum -y install cockpit-leapp $ sudo systemctl enable --now cockpit.socket これでRHELのWebコンソールにアクセスできるようになったので、 https://<RHELシステムのIPアドレスまたはホスト名>:9090 にWebブラウザでアクセスします。TCPの9090ポートが開いていないとアクセスできないので注意してください。ログイン画面が表示されるので、rootユーザーかsudoで管理コマンドを入力するパーミッションがあるユーザーでログインします。ログインしてナビゲーションメニューから Upgrade Report を選択すると、下記のようなレポート画面が表示されて、レポートされた各問題の詳細を確認できます。このレポートは /var/log/leapp/leapp-report.json を読み込んでWebコンソールで表示しています。 このWebコンソールから、問題を解決するための修復(Remediation)コマンドを実行できる場合があります。該当の問題をクリックして「Run Remediation」ボタンから修復コマンドを実行できます。 修復コマンドをまとめて実行したい場合は、レポート右上にある「Add all remediations to plan」をクリックして修復コマンドをまとめた後に、同じくレポート右上に表示される「Remediation Plan」から「Execute Remediation Plan」をクリックすることで、一覧表示された全ての修復コマンドを実行できます。 インプレースアップグレードの実行 leapp preupgrade コマンドで出力するレポートで、 Errors と Inhibitors で分類された問題が0件になったことを確認し、その他にレポートされた問題もシステムへの影響度を適宜考慮しながら修正を完了した後に、 leapp upgrade コマンドでインプレースアップグレードを実行できます。下記はRHEL7.9からRHEL8.10へのアップグレードを実行するコマンドの例です。コマンドの実行が完了するとシステムの再起動が求められるので、 sudo reboot コマンドなどで再起動します。再起動すると、RHEL8パッケージのインストールやRHUIのRHEL8リポジトリ参照の有効化が実施されて、インプレースアップグレードが完了します。 $ sudo leapp upgrade --no-rhsm --target 8.10 ...<snip>... A reboot is required to continue. Please reboot your system. Debug output written to /var/log/leapp/leapp-upgrade.log ============================================================ REPORT OVERVIEW ============================================================ HIGH and MEDIUM severity reports: 1. Difference in Python versions and support in RHEL 8 2. Packages not signed by Red Hat found on the system 3. Detected custom leapp actors or files. 4. Module pam_pkcs11 will be removed from PAM configuration Reports summary: Errors: 0 Inhibitors: 0 HIGH severity reports: 3 MEDIUM severity reports: 1 LOW severity reports: 7 INFO severity reports: 3 Before continuing, review the full report below for details about discovered problems and possible remediation instructions: A report has been generated at /var/log/leapp/leapp-report.txt A report has been generated at /var/log/leapp/leapp-report.json ============================================================ END OF REPORT OVERVIEW ============================================================ Answerfile has been generated at /var/log/leapp/answerfile Reboot the system to continue with the upgrade. This might take a while depending on the system configuration. Make sure you have console access to view the actual upgrade process. $ sudo reboot leapp upgrade コマンドでアップグレードすると、 /etc/yum/vars/ または /etc/dnf/vars/ ディレクトリにある releasever に --target オプションで指定したマイナーリリース番号( 8.8 , 8.10 , 9.4 など)が記載されます。これによって、アップグレード後のRHELシステムが、RHEL8.8やRHEL9.4などの特定のマイナーリリースに固定されるようになっています。この状態でRHELのEUSを利用したい場合、後述のEUSリポジトリ有効化手順を参照してください。RHELのEUSを使わずに最新のマイナーリリースを使いたい場合は、 /etc/yum/vars/ または /etc/dnf/vars/ ディレクトリにある releasever ファイルを削除することで、最新のマイナーリリースに対応したパッケージをRHUIからインストールできるようになります。 $ cat /etc/yum/vars/releasever 8.10 access.redhat.com また、アップグレード後のタスクとして、leappで利用したパッケージの削除などがあります。これらの詳細については、本記事末尾の参考情報に記載してある「RHEL7からRHEL8へのアップグレード」「RHEL8からRHEL9へのアップグレード」ドキュメントの「アップグレード後のタスクの実行」をご参照ください。 参考情報 leappを利用したRHELのインプレースアップグレードガイド 本記事では記載しなかった前提条件などの詳細情報が多数ありますので、Red Hatの製品ドキュメントも合わせてご参照ください。 docs.redhat.com docs.redhat.com AzureのRHELのインプレースアップグレードについては、Azureドキュメントも参照できます。 learn.microsoft.com AWS/Azure/Google CloudのRHELユーザーのRed Hatナレッジベースへのアクセスガイド AWS AWS Systems Managerの機能を利用しますので、RHELのAMIにAWS Systems Managerエージェント(SSM Agent)を手動でインストールする必要があります。 docs.aws.amazon.com docs.aws.amazon.com Azure access.redhat.com Google Cloud cloud.google.com AWS/AzureでのRHEL EUSの利用ガイド AWS access.redhat.com Azure learn.microsoft.com AzureのRHEL EUSについては、Azureテクニカルサポートチームのブログもご参照ください。 jpaztech.github.io
Ansible Advent Calendar 2024 の4日目の記事です。 みなさんメリークリスマス。Red Hatのさいとうです。 日々Ansibleを使って自動化を推進しているみなさん、 「Ansibleのモジュールやプラグインにオプションを追加してほしい」 、 「実行結果の戻り値に自分が必用とする情報を追加してほしい」 、 「不具合を修正してほしい」 といったことを七夕の短冊に書いてお祈りしたり、サンタさんにお願いしたり、IssueとしてCollectionのリポジトリにファイルしたりしたことがありますよね。僕はよくあります。 そして最後に、 「もういっそ自分で修正しちゃったほうが楽だわ」 という境地に達するはずです。そんなあなたに向けて、今日は、Ansible Collectionに対するコードコミットのお作法について書いてみようと思います。 その1: 最初にIssueとしてファイルしよう ちょっと面倒かもしれませんが、Issueとして最初にファイルしておくことをお勧めします。 レポートする際のIssueの種類は、 community.general や ansible.posix などのCollectionでは、大きく3つ分けられています。 Bug report : Create a report to help us improve Documentation Report : Ask us about docs Feature request : Suggest an idea for this project バグの場合は1 を、 ansible-doc で参照できるオプションの説明など ドキュメントに関する報告は2 を、 オプションなどの機能追加の場合は3 を選択して、あなたのリクエストをIssueとしてファイルしてください。 最終的に自分でPull Requestを送って修正する場合でも、修正内容の説明は書かなければなりません。あらかじめIssueとして詳細を説明してファイルしておけば、Pull Requestのコメントでは fixes #N のようにIssue番号だけ参照できるので、Pull Request作成時の説明で楽ができます その2: コードを修正しましょう Ansible Collectionsには、 Contributing to Ansible-maintained Collections というコントリビューター用のガイドラインが公開されているので、目を通しておいてください。 修正対象となるアップストリームのCollectionのリポジトリをforkして、作業用ブランチを作成して修正に入ります。例えばこんな感じです。 僕の場合、ブランチ名はissue_NNNとしてIssue番号にしてしまって「良い感じの名前ないかな」と悩まないようにしてます。そういう面でもIssueを先に作っておくと楽ができます。いくつもPull Requestを作っていると良い感じの名前も枯渇します :) % git clone git@github.com:<YOUR_ACCOUNT>/ansible.posix.git posix % cd posix % git checkout -b issue_NNN その3: changelog fragmentファイルを作りましょう changelog fragmentファイルを作成して、Pull Requestの種別と概要を書きます。ここにもIssueのURLを含めるとメンテナに喜ばれます。 このchangelog fragmentファイル、すくなくともansible.posixにPull Requestを送ってくれる人の9割くらいが含めるのを忘れてます。 ※含めてくる1割の人は、だいたいコレクションのメンテナです(笑)。 ファイルの命名方法は _<PRを端的に表す短いファイル名>.yml です。ファイルは changelogs/fragments/ の配下に配置してください。以下にcommunity.generalの Pull Request #9188 の例をあげます。 このとき、Issue番号をファイル名のインデックスに指定できるので、やはりあらかじめIssueをオープンしておくと便利です。Pull Request番号でもかまいませんが、この時点でまだPull Requestは作成されていないので、Pull Request番号は採番されていません。ファイル名のインデックスにPull Request番号を使用する場合は、最新の Issue/Pull Request番号+1 という面倒な確認をしなければなりません。 % cat changelogs/fragments/9188-jira-attachment-validation.yml bugfixes : - jira - remove unnecessary validation when attaching files (https://github.com/ansible-collections/community.general/pull/9188). bugfixes は、このPull Requestの カテゴリ を表しています。このカテゴリはCIプロセスの中で有効なカテゴリかどうかが確認されています。 以下によく見かけるカテゴリをご紹介します。 breaking_changes : 既存のモジュールオプションの振る舞いを完全に変えるような修正です。たとえば文字列指定だったパラメータをリスト指定に変えるといった、Playbookの記述に変更を加える必用があるような修正が該当します。この修正は、メジャーバージョンアップのみ適用されます。 major_changes : ansible-core側の変更や、collection自体が依存しているSDKの変更によって、大幅な改修が行われる場合に該当します。モジュールやプラグインレベルでは通常は使いません。 minor_changes : モジュールやプラグインに対する機能追加などがこれに当たります。バグフィックス以外はだいたいコレです。 removed_features : モジュールやプラグイン自体を削除する場合です。たとえばansible.posixからskippyプラグインを削除するといった場合に指定します。 bugfixes : モジュールやプラグインに対するバグフィックスがこれにあたります。 trivial : これはCHANGELOG.rstには記載されないような修正です。たとえばメンテナがCIプロセスの修正を行ったり、タブをホワイトスペースに修正したり、ドキュメント中のサンプルのモジュール指定をFQCNに変更したり...といった本筋とは無関係な修正がこれにあたります。 だいたい、機能追加は minor_changes 、バグ修正は bugfixes を指定しておけば間違いないです。間違っていたとしても、メンテナがコードレビューのときに指摘してくれるので、必用に応じて修正するくらいの軽い気持ちで指定してください。 changelog fragmentファイルを作るのが大事 なのです。 Collecionのメンテナは、リリースコミットの際に、このchangelog fragmentファイルから antsibull-changelog コマンドでの CHANGELOG.rst を自動生成しています。 ですから、このchangelog fragmentファイルは、現在のCollectionに対するPull Requestでは必須のファイルとなっているのです。 その4: 必用に応じてintegration testを書きましょう(Optional) minor_changes などで機能追加を行う場合は、必ずintegration testを実装してください。このテストはAnsible Playbookで書かれていて、 tests/integration/targets/ 配下にモジュール名でディレクトリが作られていて、その中に置かれています。 community.generalのintegration test ansible.posixのintegration test bugfixes などでは不要なこともありますが、 minor_changes などの機能追加では基本的に必用です。テストカバレッジなどの問題があればレビューで指摘してもらえるのでご安心を。 その5: Pull Requestを送るときの心得 Pull Requestを送るときには、以下の2点に注意してください。 その5-1: Pull Requestは、まずは Draft Pull Request で作りましょう Ansible CollectionsのPull Requestは自動でテストされます。原則的には、このテストが全て通ってはじめて人間がレビューします。テストがすべて通るまでは、 Draft Pull Request にしておいて、テストに通らなければ修正して、まずはテストを通しましょう。 自動テストに全てパスしたら、 Ready for Review ボタンをポチッと押して、 Draft Pull Request から通常のPull Requestに切り替えてください。あなたのPull Requestは、これでレビュアからのレビュー待ち状態となります。 その5-2: Maintainers are allowed to edit this pull request を確認しましょう コンフリクトの修正などの支援をメンテナから受けるためには、 Maintainers are allowed to edit this pull request のチェックボックスはONする必用があります。みなさん自身の判断でON・OFFを設定してください。 その6: コミットを1つにまとめる(Optional) レビューの中で、change requestを受けることもあるでしょう。修正が複数回にわたるとコミットメッセージの見通しが悪くなるので、複数のコミットは必用に応じてまとめるようにしています。 まとめ AnsibleのモジュールがCollectionsとして切り出された当初は、ガイドラインが整備されておらず、Collection毎になんとなくメンテナがルールを作って運用していました。しかし、現在はAnsible Communityからコントリビューターやメンテナのための統一された ガイドライン が提供されて、随分と見通しがよくなってきています。 メンテナがこれを守っていないと怒られます(怒られた)から、このガイドラインのおかげで、ずいぶんと利用者からのコードコントリビュートがしやすくなっているように感じます。みなさんも、このクリスマスにおひとつおかがでしょうか? Happy Automation :)
id:nekop です。この記事はOpenShift Advent Calendar 2024のエントリです。 最初に結論を書いておきます。OpenShift Logging ClusterLogForwarderでのVector AtLeastOnce設定はちょっとログ生成が多いタイミングがあってもログロストしない、ログ転送スループットは10MB/sくらい、対応できるログ生成レートは5k lines/sくらい、です。 vector.dev OpenShift Logging 5.9から ClusterLogForwarder のVectorにTuning項目が指定できるようになっています。6.1のAPIでは以下のようにoutputsの各type配下に定義します。 $ oc explain ClusterLogForwarder.spec.outputs.http.tuning GROUP: observability.openshift.io KIND: ClusterLogForwarder VERSION: v1 FIELD: tuning <Object> DESCRIPTION: Tuning specs tuning for the output FIELDS: compression <string> enum: none, gzip, snappy, zlib Compression causes data to be compressed before sending over the network. deliveryMode <string> enum: AtLeastOnce, AtMostOnce DeliveryMode sets the delivery mode for log forwarding. maxRetryDuration <integer> MaxRetryDuration is the maximum time to wait between retry attempts after a delivery failure. maxWrite <Object> MaxWrite limits the maximum payload in terms of bytes of a single "send" to the output. minRetryDuration <integer> MinRetryDuration is the minimum time to wait between attempts to retry after delivery a failure. この中で今回注目する項目は deliveryMode で、旧来の動作である AtMostOnce の他に、新しい指定となる AtLeastOnce が選択できます。 デフォルトの AtMostOnce ではSink(出力先)のバッファはmax_events=500のin-memory bufferで、バッファがフルになったときのアクションはwhen_full=drop_newestとなっています。つまり、500 eventsを超えてSourceから読み込まれてバッファに積まれようとしたログは即座に捨てられます。ログを大量に出力するPodをデプロイした、といったときに、かなりの量のログがロストします。逆に言うと、ログのバースト出力はほとんど捨てることになるので、ログ転送が詰まったり、リソース100%利用で張り付いたり、ログ転送先を高負荷にしてしまって結果全ノードやシステム全体に影響したり、といった様々な問題の発生を抑止できることになります。 新しい設定である AtLeastOnce ではSink(出力先)のバッファは256MBのdisk bufferになり、バッファがフルになったときのアクションはwhen_full=blockとなります。バッファフルの状況となった場合はSourceのログ読み込みが停止することになります。AtLeastOnceでもログ生成の速度がログ転送の速度を上回ったままの状態が継続するとログファイルのローテーションの都合でログはロストします。OpenShiftではコンテナのログファイルはデフォルト50Miでローテーションされます。ログローテーションされて現在のファイルの名前が変更されたり、削除されたとしても、ログ読み込みのプロセスはオープン中のファイルディスクリプタをファイルの終端まで継続して読みつづけることができるため、一回のローテーションでは問題にはなりません。Vectorのログファイルの読み込みは現在のファイルの処理が終わってから次の新規ファイルを読む、という動作をするので、ログ読み込みがブロックされたままローテーションが2回発生すると、まったく読む機会のないままローテーションされてVectorが検知できない、読み込み対象ではなくなってしまうログファイルが発生します。また、AtMostOnceの場合はログを大量に生成しているわけではない他のコンテナのログも巻き込まれてロストしますが、AtLeastOnceではログファイルのローテーションをトリガーとしてログファイル単位でロストすることになるので、基本的には大量のログを出力しているコンテナのみがログロストの対象となります。 どちらの設定にしても、ログ生成スピードがログ転送スピードより速い場合はログ転送が追いつかない状況となり、ログロストが発生します。この部分について見ていきましょう。 ログ生成は例えばshell scriptシングルスレッドループecho出力で100k lines/sほどの量が簡単に生成できます。ログ転送でのペイロードはほぼ空のメッセージのログでもメタデータがいろいろついて2kbくらいになるので、ログ行数100kの場合のログ転送量は200MBくらいになります。 VectorのAtLeastOnceでのログ転送スループットは10MB/sくらいなので、上記をベースに逆算するとバッファに貯まらないログ生成量は5k lines/sくらいです。ノード上の全コンテナ合計のログ生成レートがこれ以上ある場合、ログロストを防止するためにはコンテナ側でログ出力を抑止したり、ログ転送時にフィルタしたりといった対応が必要になります。ちなみに古いOpenShift Loggingで利用されていたfluentd構成ではログ転送の速度はVector AtLeastOnceの1/10である1MB/s程度であり、ログローテーションの速度に追いつかなくてログロスト発生する報告がかなり多かったのでした。 実際にログ転送のテストをした様子を観察してみましょう。環境はOpenShift 4.16.24 AWS IPI ap-northeast-1d, Control plane m6a.xlarge (4vCPU, 16GB mem) * 3、workerなしの3 Node Compact Cluster構成, OpenShift Logging 6.1.0です。 以下の3つのコンポーネントを作成します。 DaemonSet/logproducer: ログ生成を行うDaemonSet ClusterLogForwarder/logperf-collector: ログ転送を行うClusterLogForwarder deploy/vector-http: ログ転送先となるVector test-logperfというnamespaceを作成、vector-httpというhttpでログを受けてファイルにログを吐くカスタムのVectorコンテナをログ転送先とします。DaemonSet/logproducerは単にカウンタをログ出力するだけのPodで、1M行のログを出力します。有効化、無効化はnodeSelectorで制御します。ClusterLogForwarderでの転送元のログはlogproducer podに絞ります。 TARGET_PROJECT=test-logperf oc new-project $TARGET_PROJECT oc -n $TARGET_PROJECT create sa app-log-collector oc -n $TARGET_PROJECT adm policy add-cluster-role-to-user collect-application-logs -z app-log-collector oc -n $TARGET_PROJECT create -f - <<EOF apiVersion: observability.openshift.io/v1 kind: ClusterLogForwarder metadata: name: logperf-collector spec: serviceAccount: name: app-log-collector collection: type: vector inputs: - name: logperf type: application application: namespaces: - test-logperf filters: - name: only-logproducer type: drop drop: - test: - field: .kubernetes.labels."app" notMatches: "logproducer" outputs: - name: ext-vector-http type: http http: url: 'http://vector-http.$TARGET_PROJECT.svc:8080' tuning: deliveryMode: AtLeastOnce pipelines: - name: forward-to-ext-vector-http inputRefs: - logperf outputRefs: - ext-vector-http filterRefs: - only-logproducer EOF cat <<EOF > vector.toml expire_metrics_secs = 60 [api] enabled = true [sources.http_server_source] type = "http_server" address = "0.0.0.0:8080" decoding.codec = "json" [sinks.file_sink] type = "file" inputs = [ "http_server_source" ] path = "/tmp/vector-%Y-%m-%d.log" encoding.codec = "json" EOF oc -n $TARGET_PROJECT create configmap vector-http --from-file=vector.toml oc -n $TARGET_PROJECT create deployment vector-http --image=quay.io/openshift-logging/vector:6.1 --port=8080 --replicas=0 oc -n $TARGET_PROJECT set volume deploy/vector-http --add --name=vector-http-config --configmap-name=vector-http --mount-path=/etc/vector oc -n $TARGET_PROJECT expose deploy/vector-http oc -n $TARGET_PROJECT patch deploy/vector-http -p 'spec: template: spec: containers: - name: vector command: - /usr/bin/vector - --config - /etc/vector/vector.toml' oc -n $TARGET_PROJECT scale deploy/vector-http --replicas=1 oc create deployment logproducer --image=registry.access.redhat.com/ubi9/ubi:9.4 --replicas=0 --dry-run=client -o yaml | sed -e 's/Deployment/DaemonSet/' | oc create -f - oc patch daemonset logproducer -p 'spec: template: spec: nodeSelector: foo: bar terminationGracePeriodSeconds: 1 containers: - name: ubi command: - /bin/bash - -c - | #!/bin/bash date > /tmp/start for i in {1..1000000}; do echo $i done date > /tmp/end exec tail -f /dev/null' このスクリプトを実行すると各コンポーネントが作成されます。DaemonSet/logproducerは最初はマッチしないnodeSelectorを指定しているので、このステップではPodは作成されません。 $ oc get ds,pod NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/logperf-collector 3 3 3 3 3 kubernetes.io/os=linux 37s daemonset.apps/logproducer 0 0 0 0 0 foo=bar 2m38s NAME READY STATUS RESTARTS AGE pod/logperf-collector-85k9l 1/1 Running 0 37s pod/logperf-collector-9nqfj 1/1 Running 0 37s pod/logperf-collector-nzb27 1/1 Running 0 37s pod/vector-http-6ccddf74f5-pw2cw 1/1 Running 0 6s ログ生成して転送してみます。各ノード1M linesのログで2GBほどの転送量があり、150秒ほどログ転送が継続します。 $ oc -n $TARGET_PROJECT patch daemonset/logproducer --type json -p '[{"op":"remove","path":"/spec/template/spec/nodeSelector"}]' 結果を確認していきましょう。転送先の出力ファイル、生のコンテナログファイル、Vectorのディスクを確認していきます。 # 転送先確認、3M lines 5.8GBを156秒でファイル出力 $ oc -n $TARGET_PROJECT exec $(oc -n $TARGET_PROJECT get pod -l app=vector-http --no-headers -o name) -- sh -c "ls -hla /tmp; stat /tmp/vector*.log; wc -l /tmp/vector*.log; head -n1 /tmp/vector*.log; tail -1 /tmp/vector*.log" total 5.8G drwxrwxrwt. 1 root root 35 Dec 3 02:08 . dr-xr-xr-x. 1 root root 39 Dec 3 01:46 .. -rw-r--r--. 1 1000750000 root 5.8G Dec 3 02:10 vector-2024-12-03.log File: /tmp/vector-2024-12-03.log Size: 6183657496 Blocks: 12077472 IO Block: 4096 regular file Device: 300091h/3145873d Inode: 144116618 Links: 1 Access: (0644/-rw-r--r--) Uid: (1000750000/1000750000) Gid: ( 0/ root) Access: 2024-12-03 02:08:09.698688637 +0000 Modify: 2024-12-03 02:10:45.767486134 +0000 Change: 2024-12-03 02:10:45.767486134 +0000 Birth: 2024-12-03 02:08:09.698688637 +0000 3000000 /tmp/vector-2024-12-03.log {"@timestamp":"2024-12-03T02:08:03.064174456Z","hostname":"ip-10-0-46-252.ap-northeast-1.compute.internal","kubernetes":{"annotations":{"k8s.ovn.org/pod-networks":"{\"default\":{\"ip_addresses\":[\"10.129.0.64/23\"],\"mac_address\":\"0a:58:0a:81:00:40\",\"gateway_ips\":[\"10.129.0.1\"],\"routes\":[{\"dest\":\"10.128.0.0/14\",\"nextHop\":\"10.129.0.1\"},{\"dest\":\"172.30.0.0/16\",\"nextHop\":\"10.129.0.1\"},{\"dest\":\"100.64.0.0/16\",\"nextHop\":\"10.129.0.1\"}],\"ip_address\":\"10.129.0.64/23\",\"gateway_ip\":\"10.129.0.1\"}}","k8s.v1.cni.cncf.io/network-status":"[{\n \"name\": \"ovn-kubernetes\",\n \"interface\": \"eth0\",\n \"ips\": [\n \"10.129.0.64\"\n ],\n \"mac\": \"0a:58:0a:81:00:40\",\n \"default\": true,\n \"dns\": {}\n}]","openshift.io/scc":"restricted-v2","seccomp.security.alpha.kubernetes.io/pod":"runtime/default"},"container_id":"cri-o://52d56dd1775b20999d5a9295798f3802100cc7b2f34948308f7401665e6ffb22","container_image":"registry.access.redhat.com/ubi9/ubi:9.4","container_image_id":"registry.access.redhat.com/ubi9/ubi@sha256:970d60bb110b60c175f5b261596957a6c8ccfbd0b252d6a1d28b1655d25cb3a8","container_iostream":"stdout","container_name":"ubi","labels":{"app":"logproducer","controller-revision-hash":"67855d8d76","pod-template-generation":"3"},"namespace_id":"771ef9a2-9308-47b0-8ba6-b0a2548f9119","namespace_labels":{"kubernetes_io_metadata_name":"test-logperf","pod-security_kubernetes_io_audit":"privileged","pod-security_kubernetes_io_audit-version":"v1.24","pod-security_kubernetes_io_warn":"privileged","pod-security_kubernetes_io_warn-version":"v1.24"},"namespace_name":"test-logperf","pod_id":"f8035995-5988-46dc-a7a7-bff2ed82ed7a","pod_ip":"10.129.0.64","pod_name":"logproducer-kqt6q","pod_owner":"DaemonSet/logproducer"},"level":"default","log_source":"container","log_type":"application","message":"1","openshift":{"cluster_id":"a4e39017-6292-4e8d-9f55-8cc36ec5483c","sequence":1733191688532906012},"path":"/","source_type":"http_server","timestamp":"2024-12-03T02:08:09.639301026Z"} {"@timestamp":"2024-12-03T02:08:06.775781632Z","hostname":"ip-10-0-20-197.ap-northeast-1.compute.internal","kubernetes":{"annotations":{"k8s.ovn.org/pod-networks":"{\"default\":{\"ip_addresses\":[\"10.128.0.102/23\"],\"mac_address\":\"0a:58:0a:80:00:66\",\"gateway_ips\":[\"10.128.0.1\"],\"routes\":[{\"dest\":\"10.128.0.0/14\",\"nextHop\":\"10.128.0.1\"},{\"dest\":\"172.30.0.0/16\",\"nextHop\":\"10.128.0.1\"},{\"dest\":\"100.64.0.0/16\",\"nextHop\":\"10.128.0.1\"}],\"ip_address\":\"10.128.0.102/23\",\"gateway_ip\":\"10.128.0.1\"}}","k8s.v1.cni.cncf.io/network-status":"[{\n \"name\": \"ovn-kubernetes\",\n \"interface\": \"eth0\",\n \"ips\": [\n \"10.128.0.102\"\n ],\n \"mac\": \"0a:58:0a:80:00:66\",\n \"default\": true,\n \"dns\": {}\n}]","openshift.io/scc":"restricted-v2","seccomp.security.alpha.kubernetes.io/pod":"runtime/default"},"container_id":"cri-o://938d549f836e6d4105339c92810e9c3904cba0771a2a40388f16b8f5130dcb82","container_image":"registry.access.redhat.com/ubi9/ubi:9.4","container_image_id":"registry.access.redhat.com/ubi9/ubi@sha256:970d60bb110b60c175f5b261596957a6c8ccfbd0b252d6a1d28b1655d25cb3a8","container_iostream":"stdout","container_name":"ubi","labels":{"app":"logproducer","controller-revision-hash":"67855d8d76","pod-template-generation":"3"},"namespace_id":"771ef9a2-9308-47b0-8ba6-b0a2548f9119","namespace_labels":{"kubernetes_io_metadata_name":"test-logperf","pod-security_kubernetes_io_audit":"privileged","pod-security_kubernetes_io_audit-version":"v1.24","pod-security_kubernetes_io_warn":"privileged","pod-security_kubernetes_io_warn-version":"v1.24"},"namespace_name":"test-logperf","pod_id":"642ed500-490b-497c-bafc-170308754347","pod_ip":"10.128.0.102","pod_name":"logproducer-2zwng","pod_owner":"DaemonSet/logproducer"},"level":"default","log_source":"container","log_type":"application","message":"1000000","openshift":{"cluster_id":"a4e39017-6292-4e8d-9f55-8cc36ec5483c","sequence":1733191842616457947},"path":"/","source_type":"http_server","timestamp":"2024-12-03T02:10:45.708882902Z"} # 生ログ確認 $ oc -n $TARGET_PROJECT exec $(oc -n $TARGET_PROJECT get pod -l app.kubernetes.io/component=collector --no-headers -o name | head -n1) -- sh -c "ls -l /var/log/pods/test-logperf_logproducer-*/ubi/0.log; head -n1 /var/log/pods/test-logperf_logproducer-*/ubi/0.log; tail -n1 /var/log/pods/test-logperf_logproducer-*/ubi/0.log" -rw-------. 1 root root 51888896 Dec 3 02:08 /var/log/pods/test-logperf_logproducer-xsskx_85679f37-c4a5-40f8-bc31-3d24268d7350/ubi/0.log 2024-12-03T02:08:03.077703851+00:00 stdout F 1 2024-12-03T02:08:06.643391132+00:00 stdout F 1000000 # Vectorのcheckpointファイルとdisk buffer確認 $ oc -n $TARGET_PROJECT exec $(oc -n $TARGET_PROJECT get pod -l app.kubernetes.io/component=collector --no-headers -o name | head -n1) -- ls -lR /var/lib/vector/ /var/lib/vector/: total 0 drwxr-xr-x. 3 root root 31 Dec 3 01:45 test-logperf /var/lib/vector/test-logperf: total 0 drwxr-xr-x. 4 root root 51 Dec 2 04:52 logperf-collector /var/lib/vector/test-logperf/logperf-collector: total 0 drwxr-xr-x. 3 root root 16 Dec 2 04:52 buffer drwxr-xr-x. 2 root root 30 Dec 3 02:09 input_logperf_container /var/lib/vector/test-logperf/logperf-collector/buffer: total 0 drwxr-xr-x. 3 root root 36 Dec 2 04:52 v2 /var/lib/vector/test-logperf/logperf-collector/buffer/v2: total 0 drwxr-xr-x. 2 root root 68 Dec 3 02:10 output_ext_vector_http /var/lib/vector/test-logperf/logperf-collector/buffer/v2/output_ext_vector_http: total 14544 -rw-r-----. 1 root root 14886288 Dec 3 02:09 buffer-data-74.dat -rw-r-----. 1 root root 24 Dec 3 02:10 buffer.db -rw-r--r--. 1 root root 0 Dec 3 01:45 buffer.lock /var/lib/vector/test-logperf/logperf-collector/input_logperf_container: total 4 -rw-r--r--. 1 root root 2120 Dec 3 02:09 checkpoints.json テストを繰り返すときはdaemonset/logproducer停止、vector-http podの再作成、optionalでcollector podの再作成、daemonset/logproducer開始です。 $ oc -n $TARGET_PROJECT patch daemonset/logproducer --type json -p '[{"op":"add","path":"/spec/template/spec/nodeSelector","value":{"foo":"bar"}}]' $ oc -n $TARGET_PROJECT delete pod -l app=vector-http $ oc -n $TARGET_PROJECT delete pod -l app.kubernetes.io/component=collector $ oc -n $TARGET_PROJECT edit daemonset/logproducer # ログ生成量の変更など必要があれば設定変更 $ oc -n $TARGET_PROJECT patch daemonset/logproducer --type json -p '[{"op":"remove","path":"/spec/template/spec/nodeSelector"}]' References Tuning log payloads and delivery in RHOCP 4 Documentation - OpenShift Container Platform 4.16 / Observability / Logging / Log collection and forwarding / Configuring log forwarding - Tuning log payloads and delivery
Red Hat で Ansible のソリューションアーキテクトをしている中島でございます。 本エントリーは Ansible Advent Calendar 2024 の3日目の記事となります。 Ansible Advent Calendar 2024 にはAnsible 関する様々なTIPSやナレッジが投稿されておりますの、Ansible を触っている方はご一読いただくと、自動化のステップアップのきっかけを得られるかもしれません。 さて、Ansible には Event-Drive Ansible(以下EDA)という機能があります。これは、監視システムや分析システムなどの周辺システムからのメッセージを受取り、そのメッセージ内容によって対応するAnsibleの自動化を起動するための機能です。 この機能を使うことで、監視アラートへの自動対応、セキュリティ侵害検知への自動対応などを行うことが可能となります。EDA自身のイメージについて過去記事をご参照ください。 Event-Driven Ansible + Zabbix で実現する障害対応の自動化 Event-Driven Ansible の始め方 Event-Driven Ansible と IBM Turbonomic / Instana の連携 Ansible Automation Platform 2.4 注目の新機能紹介 ここからが本題となります。 このようなイベント駆動型の仕組みを構築しようとした時に最も問題になるのが「イベントの精度」です。 「アラートAが来たら自動化1を流す」という仕組みを作った時に、アラートAが正確ならば何ら問題がないですが、現実のシステムではアラートAが何度も送信されてしまったり、別のアラートBに起因してアラートAが送信されるケースもあります。このようにアラートが不正確では当然自動対応をするEDA側も想定外の自動化を実行してしまう可能性が出てきます。もちろんアラート送信側で精度を上げることも必要ですが、100%完璧な仕組みを作ることは困難です。そのため、自動対応を行うEDA側でも「アラートの不正確さ」をある程度吸収する仕組みが必要となります。 今回は、そんなアラートの不正確さを吸収するEDA機能である「Throttle(スロットル)」機能をご紹介します。 Throttle は EDA の rulebook の中で定義することができます。実際に rulebook を見てみましょう。 --- - name: Listen for webhook 8112 for throttle demo hosts: all sources: - ansible.eda.webhook: host: 0.0.0.0 port: 8112 rules: - name: throttle enabled condition: >- event.payload.message == 'enabled' throttle: once_within: 1 minutes group_by_attributes: - event.payload.message actions: - run_job_template: name: throttle_enable_job organization: Default - name: throttle disabled condition: >- event.payload.message == 'disabled' actions: - run_job_template: name: throttle_disabled_job organization: Default この rulebook ではポート8112番でWebhookを待ち受け、受け取ったイベントに応じて、2つのルールが定義されています。 ルール 条件 実施するアクション Throttle name: throttle enabled 受信したデータが以下の条件を満たした時 event.payload.message == 'enabled' 以下のジョブを起動 throttle_enable_job on name: throttle disabled 受信したデータが以下の条件を満たした時 event.payload.message == 'disabled' 以下のジョブを起動 throttle_disable_job off name: throttle enabled では以下の記述によって、Throttle が有効化されています。 throttle: once_within: 1 minutes group_by_attributes: - event.payload.message この記述の説明は後回しにして、実際にこの2つのルールに対して、複数回のイベントを送信して挙動を確認してみます。 まず最初はThrottle無効のルールを起動するために event.payload.message == 'disabled' を含むメッセージを5回送信してみます(このイベント送信もAAPから行っています)。定義通りに動けば、 throttle_disable_job が5回起動されるはずです。実際に以下の動画で確認してください(想定通り5回起動されてしまっています)。 次に、Throttleを有効にした event.payload.message == 'enabled' を5回送信しています。こちらも動画で確認してください(同一イベントへの対応が抑制され、1回しか起動されません) このように Throttle 機能を使うことで、同一イベントに対する自動化の起動を抑制することが可能です。 では挙動が確認できたところで、Throttle の基本的な記述について確認していきます。といって、マニュアルに記載されていますので、重要な部分のみ抜粋します。 https://ansible.readthedocs.io/projects/rulebook/en/latest/conditions.html#throttle-actions-to-counter-event-storms-reactive まずイベント受信した場合の「自動化の起動タイミング」を制御するための記述として、 once_within : イベントを受信したら即自動化を起動して、その後指定した時間内は同一イベントを無視する once_after : イベントを受信したら指定時間分だけ待ち、その間に受け取った同一イベントを無視する。指定時間経過後に自動化を実行する また、「何を同一イベントとするか」については group_by_attributes で指定します。受信したメッセージ含まれるデータを指定し、指定されたデータが同じものを「同一イベント」と判断します。 今回ご紹介した Throttle 機能を使うことで、イベント駆動の自動化は飛躍的に使いやすくなり、適用できるシーンが増えます。9割正確なアラートシステムと、9割正確なrulebook の組み合わせは99%の精度で処理できるからです。単独で99%の精度を得るのはコストが高すぎて実現が困難ですが、90%の精度であれば現実的なコストで実装が可能です。 またEDAはRed Hat Ansible Automation Platform に含まれる標準機能ですので、すでにサブスクリプションをお持ちの方は追加コスト無しで利用することができます。 ぜひ、この機能を活用して、自動化の適用範囲を広げ、日々の作業の効率化役立ててください。
Red Hat で Java 関連を担当している伊藤ちひろです。 本記事は、Jakarta EE 10と一緒に MyBatis を使う方法を紹介します。 MyBatis 自体の使い方は説明しません。 Jakarta EE 10で MyBatis を使う方法に焦点をあてます。 MyBatis は Java SE や Jakarta EE の仕様と連携できます。 本記事では以下の構成で MyBatis を使ってみます。 MyBatis を Contexts and Dependency Injection (CDI) で使えるようにする トランザクション管理は Jakarta Transactions コネクション管理はAPサーバから javax.sql.DataSource を提供 サンプルは JBoss EAP 8.0 で動作を確認しています。 サンプルはこちら プロジェクトの設定 MyBatis を CDI と組み合わせて使うには、 mybatis と mybatis-cdi という2つの依存を追加します。 これらはどちらも org.mybatis というグループIDです。 アプリケーションの pom.xml に以下のように追記します。 <dependency> <groupId> org.mybatis </groupId> <artifactId> mybatis-cdi </artifactId> <version> 2.1.0 </version> </dependency> <dependency> <groupId> org.mybatis </groupId> <artifactId> mybatis </artifactId> <version> 3.5.16 </version> </dependency> 設定ファイル 次に、MyBatisの設定ファイルです。 ここでは、以下を設定します。 トランザクションのライフサイクル管理をアプリケーションサーバに任せる(transactionManager要素) データソースをアプリケーションサーバに定義済みのものを使う (dataSource要素) アプリケーションサーバで、 data_source プロパティに設定してあるデータソースを作成する必要があります。 また、あとのステップで設定が正しく行われたかどうかを確認するため、ログを出力するように設定しています。 src/main/resources/mybatis-config.xml <? xml version = "1.0" encoding = "UTF-8" ?> <! DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration> <settings> <setting name = "logImpl" value = "STDOUT_LOGGING" /> </settings> <environments default = "Postgres" > <environment id = "Postgres" > <transactionManager type = "MANAGED" /> <dataSource type = "JNDI" > <property name = "data_source" value = "java:jboss/datasources/PostgreSQLDS" /> </dataSource> </environment> </environments> <mappers> <!-- マッパーファイルの一覧を記述 --> </mappers> </configuration> ファクトリ 最後に、MyBatis のクライアントを CDI で使えるようにするため、CDI の Producerを作成します。 この Producer は org.apache.ibatis.session.SqlSessionFactory を作成します。 複数のデータベースにアクセスする場合は、Producer に限定子(Qualifier) を設定することで、 SqlSessionFactory を使い分けられるようにします。 以下は、Producer のサンプルコードです。 上述の設定ファイルを使用しています。 package org.example; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Produces; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.mybatis.cdi.SessionFactoryProvider; import java.io.IOException; import java.io.InputStream; @Dependent public class SqlSessionFactoryProducer { @Produces @ApplicationScoped @SessionFactoryProvider public SqlSessionFactory produceFactory() throws IOException { InputStream fileStream = Resources.getResourceAsStream( "mybatis-config.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(fileStream); return sqlSessionFactory; } } 動作確認 Producer で SqlSessionFactory を作成できたかどうか確認します。 アプリケーションをデプロイすると以下のようなログが出力されれば成功です。 もし、先頭の 2 行だけが出力され、最後の Managed SqlSession: の行が出力されていない場合は失敗です。 21:22:11,832 INFO [org.mybatis.cdi.MybatisExtension] (MSC service thread 1-8) MyBatis CDI Module - SqlSessionFactory producer SqlSessionFactoryProducer.produceFactory 21:22:11,851 INFO [org.mybatis.cdi.MybatisExtension] (MSC service thread 1-8) MyBatis CDI Module - Activated 21:22:11,851 INFO [org.mybatis.cdi.MybatisExtension] (MSC service thread 1-8) MyBatis CDI Module - Managed SqlSession: org.apache.ibatis.session.SqlSession, org.apache.ibatis.session.SqlSession MyBatisを使う ログがきちんと出力されるようになったら、 org.apache.ibatis.session.SqlSession のオブジェクトを DI できます。 これは、CDI で普通に @Inject を付けて DI します。 package org.example; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import org.apache.ibatis.session.SqlSession; import java.util.List; @Path ( "/hello" ) public class HelloResource { @Inject SqlSession sqlSession; @GET @Produces (MediaType.APPLICATION_JSON) public List<SampleEntity> hello() { return sqlSession.selectList( "findList" ); } } 参考:Java EE + iBATIS から Jakarta EE + MyBatis への移行 MyBatis の前身である iBATIS は、未だに Java EE と一緒によく使われています。 iBATIS から MyBatis へ移行する場合は、以下が必要です。 使用するクラスとメソッドの変更 マッパーファイルの変更 使用するクラスは com.ibatis.sqlmap.client.SqlMapClient から org.apache.ibatis.session.SqlSession に変わります。 メソッドも変わるため、Javadocを見ながら適切なものへ変更していきましょう。 既存のマッパーファイルが多い場合には手作業で変換するのは大変です。 そのため、変換ツールが公式から公開されています。 また、公式以外でも変換ツールを公開されている方もいらっしゃいました。 GitHub - mybatis/ibatis2mybatis: Tool to convert iBATIS 2 xml files to MyBatis3 GitHub - ogasada/ibatisToMyBatis3: The tool converts sqlmap files for iBatis to MyBatis3. 私が使った感想としては、マッパーファイルが古すぎるとどちらも変換できませんでした。 これは、マッパーファイルのDOCTYPE要素に記載されているDTDのホスト名が異なるためでした。 この問題に遭遇した場合はホスト名の部分を ibatis.apache.org に変更してから変更してください。
【2026年1月追記】最新の情報を元に内容をアップデートしました! こんにちは、Red HatでOpenShift関連のプリセールスをしている北村です。 今回から "Developer Hub 実践" と題して、不定期にRed Hat Developer Hub (以下Developer Hub)関連の記事をアップしていこうと思います。 記事の内容はDeveloper Hubの具体的な設定方法など、 Developer Hubのツールとしての使い方を掘り下げていくものを想定しています。 以前「 Red Hat Developer Hub (Backstage) でGolden Pathを作ろう 」というタイトルでQiitaに記事をあげていますが、Developer Hubのバージョンも上がりいくつか変更が必要な箇所があるので、改めてここで実装方法を紹介していきます。 第1回はDeveloper Hubのインストール方法です。 【第1回】Developer Hubをインストールしてみよう ←この記事 【第2回】GitHubを使用した認証を実装しよう 【第3回】GitLabを使用した認証を実装しよう 【第4回】Componentを作成・登録しよう 【第5回】Software Templateを使ってアプリのデプロイをセルフサービス化しよう 【第6回】TechDocsを作成・登録しよう 【第7回】Golden Pathの実装をマスターしよう - 前編 【第8回】Golden Pathの実装をマスターしよう - 後編 なお、Developer Hubは別途Subscriptionが必要ですが、 Red Hat 製品トライアルセンター で60日間の無償トライアルを利用することができます。 気になる方はぜひこちら↓にアクセスして試してみてください。 https://www.redhat.com/en/technologies/cloud-computing/developer-hub/trial (本題の前に)Developer Hubとは? Developer HubはOSSであるBackstageをベースとした開発者ポータルです。 Backstageが持つ機能に加え、以下のような独自の機能・サービスを提供しています。 Red Hatが作成したサンプルのGolden Path Template 様々なツール(GitHubやGitLab、ArgoCDなど)と連携するためのプリセットプラグイン ポータル活用のための便利な機能を追加する独自プラグイン 継続的なUI改善 Backstageのコア機能とプラグインに対するエンタープライズレベルのサポート Developer HubはOpenShiftだけでなく、EKSやAKS、GKE上にもデプロイすることができます。 2026年1月現在では、バージョン1.8が最新になります。 そもそもBackstageってなんなの?という方は以下のスライドを参考にしてみてください。Backstageの基本的なコンセプトや機能が紹介されています。 www.docswell.com 前提条件 クラスター環境 Red Hat OpenShift on AWS(ROSA): 4.20.10 Cluster API Endpoint: Public GitHub github.com アカウント1つ 作業端末 Macbook oc : 4.20.11 user-role: cluster-admin Developer Hub インストール手順 Operatorのインストール まずはOperatorをインストールしていきます。ここは全部デフォルトのままでOKです。 Developer Hubのデプロイ Operatorをインストールできたら、まずDeveloper Hubをデプロイする rhdh Namespaceを作成します。 oc new-project rhdh 次にDeveloper Hubをデプロイしていきます。Developer Hubのデプロイには以下のyamlファイルを使います。 developer-hub.yaml apiVersion : rhdh.redhat.com/v1alpha4 kind : Backstage metadata : name : developer-hub namespace : rhdh labels : app.kubernetes.io/name : backstage spec : application : appConfig : configMaps : - name : app-config-rhdh mountPath : /opt/app-root/src extraEnvs : secrets : - name : secrets-rhdh route : enabled : true dynamicPluginsConfigMapName : dynamic-plugins-rhdh database : enableLocalDb : true deployment : patch : spec : replicas : 1 yamlをデプロイします。 oc apply -f developer-hub.yaml このyamlでは、Developer Hubに対して以下の3つのConfigmap/Secretを設定しています。 app-config-rhdh : Developer Hub 内のさまざまな設定を管理するための yaml ファイル secrets-rhdh : app-config-rhdh などで参照する環境変数をこの Secret を使って設定する dynamic-plugins-rhdh : Dynamic Plugins のインストール設定用 yaml ファイル このカスタムリソースの作成によってDeveloper Hub用のPodやService,Routeが作成されますが、 app-config-rhdh / dynamic-plugins-rhdh のConfigmapや secrets-rhdh の SecretがないためPodが起動しません。そのため、この3つのリソースをデプロイしていきます。 app-config Configmapのデプロイ ここでは最低限のConfig内容を記載しています。 app-config-rhdh.yaml kind : ConfigMap apiVersion : v1 metadata : name : app-config-rhdh namesapce : rhdh annotations : rhdh.redhat.com/backstage-name : developer-hub data : app-config-rhdh.yaml : | backend : auth : externalAccess : - type : legacy options : secret : “${BACKEND_SECRET}” subject : legacy-default-config baseUrl : ${BASE_URL} cors : origin : - ${BASE_URL} app : title : Red Hat Developer Hub baseUrl : ${BASE_URL} analytics : segment : enabled : false yamlをデプロイします。 oc apply -f app-config-rhdh.yaml secrets-rhdh Secretのデプロイ 次に各種変数を渡すためのSecretを作成します。ここでの変数はDeveloper HubのPod内で環境変数として設定され、app-configなどに反映することができます。 secrets-rhdh.yaml apiVersion : v1 kind : Secret metadata : name : secrets-rhdh namespace : rhdh stringData : BASE_URL : "https://backstage-developer-hub-rhdh.apps.<ROSAドメイン>" BACKEND_SECRET : "<バックエンド認証キー>" BACKEND_SECRET にはbase64でエンコードされた任意の文字列を使用します。例えば以下のコマンドの出力結果などを使いましょう。 node -p 'require("crypto").randomBytes(24).toString("base64")' yamlをデプロイします。 oc apply -f secrets-rhdh.yaml dynamic-plugins-rhdh Configmapのデプロイ 最後にdynamic-pluginのインストール要否を設定するConfigmapをデプロイします。こちらも一旦は最低限の値のみを設定します。 dynamic-plugins-rhdh.yaml kind : ConfigMap apiVersion : v1 metadata : name : dynamic-plugins-rhdh namespace : rhdh annotations : rhdh.redhat.com/backstage-name : developer-hub data : dynamic-plugins.yaml : | includes : - 'dynamic-plugins.default.yaml' yamlをデプロイします。 oc apply -f dynamic-plugins-rhdh.yaml 設定の反映 すべてのConfigmapとSecretのデプロイが完了すると、Podがデプロイされます。 しばらくするとPodがrunningになるので、以下のコマンドでRouteのURLを取得し、ログインします。 oc get route -n rhdh backstage-developer-hub -o jsonpath={.status.ingress[0].host} ログイン画面が表示されれば、ひとまずインストール完了です。 おわりに 今回はひとまずDeveloper Hubのデプロイにフォーカスしましたが、単なるポータルのガワができただけなので、このままではポータルとしての価値はほとんどありません。 次回以降の記事では、ここでインストールした環境をベースにどんどんカスタマイズしていきます。乞うご期待!
こんにちは。ソリューションアーキテクトの瀬戸です。 今回はApache Camelアプリケーションの開発環境のセットアップをしてサンプルアプリを確認してデプロイまでをしてみたいと思います。 Apache Camelって何よ?って思った人は、蒸野さんが書いているブログ記事: Apache Camel 超入門 を参照してください。 rheb.hatenablog.com 以前Red HatではFuseという名前でApache Camelを製品化して販売していました。 今はRed Hat build of Apache Camelという名前で製品化されているのですが、Red Hat build of Apache Camelに変わった後も複雑な経緯によってドキュメントの体系が変わっており、細心のドキュメントが見つけにくくなっています。 現時点(2024年11月時点)では、 製品ドキュメントのページ から Red Hat build of Apache Camelのリンクをたどったもの が最新のドキュメントです。 それ以外については、すでにリタイヤしているものや、もうすぐリタイヤするもののドキュメントとなります。 googleで apache camel red hatで検索するとFuseのドキュメントが最初に引っかかってしまいますが、そちらはすでに古いものとなっています。 現時点(2024年11月)でのサポートされている最新のバージョンはRed Hat build of Apache Camel 4.4です。 ドキュメントのページによってはRed Hat build of Apache Camel for Spring Boot 3.20までしかバージョン一覧から選べないものもありますのでご注意ください。 重ねますが、以下が2024年11月時点での最新のドキュメントになりますのでご注意ください。 docs.redhat.com Apache Camelを実際に使用する Apache Camel自体はただのライブラリです。動かすためには別途アプリケーションサーバーが必要になります。 現時点ではサポートされる環境としてSpring-BootかQuarkusを選択することができます。Spring-Bootを選択することで多くの人が慣れているSpring-BootのAPIを使用する事ができます。 Quarkusを選択するとSpring-Bootよりも軽快に動作することが期待できます。 今回は、Spring-Bootを利用します。 Note: Camelのランタイムとして他にCamel Kもありますが、Camel Kのサポートは来年半ばには終了するため、新規に使い始めることは出来ません。 https://access.redhat.com/ja/articles/7083689 Spring-BootでApache Camelで開発するためにはJavaの開発環境が必要になります。OpenJDKのインストールやMavenの設定が必要になります。 設定をしたことがない場合は、以下の記事で説明しています。以下の記事ではJBoss EAPの開発環境を構築していますが、全く同じです。 rheb.hatenablog.com 開発環境さえあれば Red Hat build of Apache Camel for Spring Boot のスタートガイド の通りに行えばプロジェクトを作成できますが、簡単に作成するために今回はMavenのアーキタイプを利用します。 MavenのアーキタイプはJavaアプリケーションのテンプレートをMaven Repositoryに登録しておく仕組みです。 いくつかのパラメーターを入力することでMavenでのアプリケーション開発のサンプルを簡単に作ることができます。 アーキタイプの詳細についてはMavenのウェブサイトを参照してください。 maven.apache.org また、Eclipse等を使用する事でどのようなアーキタイプが登録されているかを検索することもできます。 次の図はEclipseで新規プロジェクトの作成時にMavenアーキタイプの一覧を表示しています。 Maven アーキタイプの検索 さて、話はそれましたが、Red Hatのサポートの元Apache Camelを使用する場合にどのアーキタイプを指定するかについてはドキュメントに記載されています。 docs.redhat.com ドキュメント通りにコマンドを叩きます。 mvn archetype:generate -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-spring-boot -DarchetypeVersion=4.4.0.redhat-00033 -DgroupId=com.redhat -DartifactId=csb-app -Dversion=1.0-SNAPSHOT -DinteractiveMode=false ※このうち、-DgroupIdと-DartifactId、-Dversionについては自由に変更することができます。artifactIdがフォルダ名になることだけ注意してください。 この指定のまま作成したプロジェクトをgithub上に準備しています。 github.com このアーキタイプから作成されたプロジェクトにはサンプルアプリケーションが含まれています。 先のドキュメント通りやれば動くことは確認ができるので、中身のソースを見てみましょう。 Javaのソースコードとしては次の4つが含まれています。 MySpringBean.java CamelからJavaのメソッド呼び出しのサンプルを実行するために準備されたクラス MySpringBootApplication.java Spring Bootアプリケーションの起動に使用するブートストラップ MySpringBootRouter.java Camelの設定が含まれるクラス MySpringBootApplicationTest.java Camelをテストするために利用するクラス この中で見るべきクラスはMySpringBootRouter.javaとMySpringBootApplicationTest.javaです。 まずは、MySpringBootRouter.javaを見ていきましょう。 MySpringBootRouter.java package com.redhat; import org.apache.camel.builder.RouteBuilder; import org.springframework.stereotype.Component; /** * A simple Camel route that triggers from a timer and calls a bean and prints to system out. * < p /> * Use < tt > @Component </ tt > to make Camel auto detect this route when starting. */ @Component public class MySpringBootRouter extends RouteBuilder { @Override public void configure() { from( "timer:hello?period={{timer.period}}" ).routeId( "hello" ) .transform().method( "myBean" , "saySomething" ) .filter(simple( "${body} contains 'foo'" )) .to( "log:foo" ) .end() .to( "stream:out" ); } } ここではApache Camelの特徴であるJava DSLを使った処理を確認できます。Apache Camelではメソッドチェーンを利用して処理を組み立てていきます。何をしているかは読めばなんとなくわかるでしょう。 {{}}で囲われてる部分はSpring-Bootの機能を使用してapplication.propertiesから値が読み込まれています。 application.propertiesには timer.period=2000 と指定されているため、 timer:hello?period={{timer.period}} は実際には timer:hello?period=2000 として解釈されています。 Apache Camelではモジュールを組み合わせることで処理を追加でき、これはTimerコンポーネントで実装されています。 docs.redhat.com Maven依存関係を追加して、オプションを追加してあげることで動作します。 慣れてる人はどういうコンポーネントがあるのか、パラメーターとして何を指定すればいいのかある程度わかるのですが、慣れてない人は途方に暮れてしまいます。初心者でもわかりやすいようにRed HatではkaotoというRed Hat Build of Apache Camel 4.x 向け開発ツールを提供しています。 詳細については古市さんが書いてくださってるのでそちらを参照してください。 rheb.hatenablog.com MySpringBootApplicationTest.java 続いてテストの方を見ていきます。Apache CamelではJUnitをフォローする形でテスト用のツールが付いています。 package com.redhat; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.AdviceWith; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.spring.junit5.CamelSpringBootTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest @CamelSpringBootTest public class MySpringBootApplicationTest { @Autowired private CamelContext camelContext; @Autowired private ProducerTemplate producerTemplate; @Test public void test() throws Exception { MockEndpoint mock = camelContext.getEndpoint( "mock:stream:out" , MockEndpoint. class ); AdviceWith.adviceWith(camelContext, "hello" , // intercepting an exchange on route r -> { // replacing consumer with direct component r.replaceFromWith( "direct:start" ); // mocking producer r.mockEndpoints( "stream*" ); } ); // setting expectations mock.expectedMessageCount( 1 ); mock.expectedBodiesReceived( "Hello World" ); // invoking consumer producerTemplate.sendBody( "direct:start" , null ); // asserting mock is satisfied mock.assertIsSatisfied(); } } こちらも何をしようとしているのかは簡単にわかるのではないかと思います。 AdviceWithクラスの中でApache Camelの中身の設定(fromとto)を書き換えています。 その結果、実行し出力される内容が想定通りか(mock#expectedBodiesReceivedの内容と同じか)を確認しています。 Apache CamelはインテグレーションツールとしてIN/OUTを固めやすいため、テストもしやすいです。 OpenShiftへのデプロイ 今回のApache Camelは通常のSpring-Bootアプリケーションのため、前回の記事、 Spring-Bootアプリケーションのbootable jarをOpenShiftにデプロイする にて書いたとおりの手順でデプロイできます。 ただ、前回の記事で、 OpenShiftはCI/CDに関わる機能も備えており、OpenShift上でGitHub等から直接ソースコードを取得してビルドをし、デプロイすることができます。 と書きましたが、そちらの説明をしていないため、今回はその説明をしたいと思います。 OpenShiftへのソースコードを指定してデプロイする場合のMavenの設定 OpenShiftへのデプロイは柔軟なため、いろいろデプロイする方法はあるのですが、ソースコードを直接取得し、OpenShift上でビルドし、デプロイするために一番簡単な方法はOpenShiftのイメージストリームの仕組みを使う事です。 詳細な説明は除きますが、そのためにはMavenのpom.xmlにopenshiftという名前の付いたprofileを準備しておく必要があります。 今回のアーキタイプで指定したプロジェクトではすでに設定されています。 <? 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 http://maven.apache.org/maven-v4_0_0.xsd" > <modelVersion> 4.0.0 </modelVersion> (中略) <profiles> <profile> <id> openshift </id> <build> <defaultGoal> install </defaultGoal> <plugins> <plugin> <groupId> org.eclipse.jkube </groupId> <artifactId> openshift-maven-plugin </artifactId> <version> 1.16.2.redhat-00017 </version> <executions> <execution> <goals> <goal> resource </goal> <goal> build </goal> <goal> apply </goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile> </profiles> </project> openshift-maven-pluginはfabric8-maven-plugin から置き換えられたものです。OpenShift上のリソースを操作することもできます。どういうことができるのかについてはドキュメントを参照してください。 eclipse.dev コマンドライン上から単純にgithubのリポジトリを指定して実行することでデプロイすることができます。 oc new-app https://github.com/ssetoredhat/csb-app この設定は他のSpring-Bootアプリケーションやfat-jarを生成するアプリケーションでも有効です。ソースコードから自動的にmavenを使用してビルドをし、デプロイをしてくれます。 おわり Apache Camelのドキュメントの紹介からプロジェクトの始め方、OpenShiftのデプロイまでを簡単に説明しました。 簡単に試せるのが利点だと思いますので、ぜひ参考にしてみてください。
こんにちは。Red Hatのソリューションアーキテクトの瀬戸です。 OpenShiftはCI/CDに関わる機能も備えており、OpenShift上でGitHub等から直接ソースコードを取得してビルドをし、デプロイすることができます。 しかしながら、すでにGitHub ActionsなどCI/CD基盤が外部に構築されており、OpenShiftをアプリケーション稼働環境としてだけ動作させたい場合もあります。 その場合にどうやってコマンドラインでデプロイするのかについて説明します。 コマンドラインツールのインストール OpenShiftをコマンドラインで操作するためにはoc コマンドが必要です。 OpenShift Container Platform ダウンロードページ からダウンロードすることができます。 バージョンドロップダウンメニューで適切なバージョンを選択し、動作させたいOSを選択してダウンロードしてください。 ocコマンドのダウンロード アカウントがない場合は Red Hat Developer Program でアカウントを作成することができます。 ダウンロードしたら、解凍をし、PATHの通った場所に設定してください。 ocコマンドからのOpenShiftへのログイン ログインするためのコマンドは OpenShiftのWebコンソールにログインした後に右上のユーザー名をクリックすることで表示されます。 ログインコマンドのコピー ログイン成功 アクセスできるプロジェクトが表示されます。プロジェクトはOpenShift内でまとめて管理される単位です。名前空間(namaspace)とも呼ばれます。 デフォルトで指定されている場合もありますが、指定されていない場合はどのプロジェクトで操作するのか(jarをデプロイするのか)を指定する必要があります。 この例ではsseto-devというのがあるので、以下のコマンドでプロジェクトを切り替えます。 oc project sseto-dev 新しくプロジェクトを作成したい場合は以下のコマンドを実施します。 oc new-project [新しいプロジェクト名] jarのデプロイ これで環境の設定が終わったのでjarをデプロイしていきます。 今回は spring-petclinic を使用します。ローカルにダウンロードして、次のコマンドで実行可能jarを作成できます。 mvnw package -Dmaven.test.skip NOTE:自分のアプリケーションを使用する場合はポート番号:8080でウェブサーバーが実行されるように設定してください。 ここまで来たらいくつかのコマンドを実行するだけでデプロイすることができます。 最初にどのコンテナイメージを使用してビルドをするのかの設定を行います。ここでいうビルドはJavaのビルドではなく、コンテナイメージのビルドです。 oc new-build --name=spring-petclinic --binary=true --image-stream=openshift/ubi8-openjdk-21:1.18 --strategy=source コンテナイメージの指定 ここではコマンドの詳細な解説はしませんが、openjdk-21のイメージを使用しています。openjdk-17 のイメージを使用する事もできます。 使用しているイメージストリームとは何かに興味がある場合はこちら。 設定したら、コンテナイメージのビルドを行います。 oc start-build spring-petclinic --from-dir=target --follow ※--from-dirにはjarの含まれているディレクトリを指定してください。 Dockerやpodmanでコンテナイメージのビルドをしたことがる人はログを眺めれば何が行われているかわかるのではないかと思います。 oc start-build spring-petclinic --from-dir=target --follow Uploading directory "target" as binary input for the build ... ........ Uploading finished build.build.openshift.io/spring-petclinic-1 started Receiving source from STDIN as archive ... time="2024-10-25T01:29:24Z" level=info msg="Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled" I1025 01:29:24.537537 1 defaults.go:112] Defaulting to storage driver "overlay" with options [mountopt=metacopy=on]. Caching blobs under "/var/cache/blobs". Trying to pull image-registry.openshift-image-registry.svc:5000/openshift/ubi8-openjdk-21@sha256:4f35566977c35306a8f2102841ceb7fa10a6d9ac47c079131caed5655140f9b2... Getting image source signatures Copying blob sha256:dc35b837139a95d1b9f7f7b0435a024a74ab972416bdc248f3f608c9f917a753 Copying blob sha256:eca9236fb686825c1ec7ba1f1b339f6300ed2d4fffdf50611dde66cb8f6eeaa9 Copying config sha256:6cc5e74a214a5396231402ca4386dceb067e112b8aad022961c5b51ded628172 Writing manifest to image destination Generating dockerfile with builder image image-registry.openshift-image-registry.svc:5000/openshift/ubi8-openjdk-21@sha256:4f35566977c35306a8f2102841ceb7fa10a6d9ac47c079131caed5655140f9b2 Adding transient rw bind mount for /run/secrets/rhsm STEP 1/9: FROM image-registry.openshift-image-registry.svc:5000/openshift/ubi8-openjdk-21@sha256:4f35566977c35306a8f2102841ceb7fa10a6d9ac47c079131caed5655140f9b2 STEP 2/9: LABEL "io.openshift.build.image"="image-registry.openshift-image-registry.svc:5000/openshift/ubi8-openjdk-21@sha256:4f35566977c35306a8f2102841ceb7fa10a6d9ac47c079131caed5655140f9b2" "io.openshift.build.source-location"="/tmp/build/inputs" "io.openshift.s2i.destination"="/tmp" STEP 3/9: ENV OPENSHIFT_BUILD_NAME="spring-petclinic-1" OPENSHIFT_BUILD_NAMESPACE="megascus-dev" STEP 4/9: USER root STEP 5/9: COPY upload/src /tmp/src STEP 6/9: RUN chown -R 185:0 /tmp/src STEP 7/9: USER 185 STEP 8/9: RUN /usr/local/s2i/assemble INFO S2I source build with plain binaries detected INFO Copying binaries from /tmp/src to /deployments ... (中略) INFO Cleaning up source directory (/tmp/src) STEP 9/9: CMD /usr/local/s2i/run COMMIT temp.builder.openshift.io/megascus-dev/spring-petclinic-1:4f08c806 Getting image source signatures Copying blob sha256:1053d00b8e292c8a36bef630a0f4977b29da4e2fd60ac9425e0fcd1f7c1108d5 Copying blob sha256:5526728ef275eaed3e27ae09fdc66e4f9e0a1f07785a8425376b961dc531ce91 Copying blob sha256:d3ff415f0a4679ddb9520781578f8a82a9f74cf4fa6a9d0c266f9fba8ff69914 Copying config sha256:869623b4df3f7c0abc8957cc40d220b9083570115d534af95f36bbe5bb86654a Writing manifest to image destination --> 869623b4df3f Successfully tagged temp.builder.openshift.io/megascus-dev/spring-petclinic-1:4f08c806 869623b4df3f7c0abc8957cc40d220b9083570115d534af95f36bbe5bb86654a Pushing image image-registry.openshift-image-registry.svc:5000/megascus-dev/spring-petclinic:latest ... Getting image source signatures Copying blob sha256:d3ff415f0a4679ddb9520781578f8a82a9f74cf4fa6a9d0c266f9fba8ff69914 Copying blob sha256:dc35b837139a95d1b9f7f7b0435a024a74ab972416bdc248f3f608c9f917a753 Copying blob sha256:eca9236fb686825c1ec7ba1f1b339f6300ed2d4fffdf50611dde66cb8f6eeaa9 Copying config sha256:869623b4df3f7c0abc8957cc40d220b9083570115d534af95f36bbe5bb86654a Writing manifest to image destination Successfully pushed image-registry.openshift-image-registry.svc:5000/megascus-dev/spring-petclinic@sha256:89d446804522d1a49c278bc72b5644eee11afd7de50ab452cfdff7183a731351 Push successful ビルドが完了したらコンテナイメージを基にPod(サーバー)を立てます。 oc new-app spring-petclinic サーバーの起動 OpenShiftではPod(サーバー)を実行した後に外部からアクセスできるようにする設定が必要になります。 次のコマンドを実行します。 oc create route edge --service=spring-petclinic 外部への公開 動作確認はウェブコンソールから行った方がやりやすいのでウェブコンソールにアクセスします。 左のメニューからトポロジーを開いてみてください。デプロイしたPod(サーバー)が表示されているはずです。 トポロジー Pod(サーバー)の右上をクリックすることでアプリケーションにアクセスすることができます。 Pod アプリケーションの画面 アプリケーションを入れ替えたい場合(jarを更新したい場合)は以下のコマンドを再実行します。 oc start-build spring-petclinic --from-dir=target --follow 自動的にアプリケーションが更新されるはずです。 まとめ 簡単にjarのコマンドラインでのアップロード方法を説明しました。既存のアプリケーションをOpenShiftで試しに動かしてみたい場合等に使用する事ができます。 OpenShift環境がなくても試したい場合は OpenShift Developer Sandbox で無料で試すことができます。また、ローカルで確認したい場合はOpenShift Localを使用する事もできます。 OpenShift Localの場合、デフォルトでかなり小さいインスタンスサイズになってますのでいくつか追加で設定をすると快適に使用できます。使用する場合はこちらの記事を参考にしてみてください。 rheb.hatenablog.com ちなみに、jarを指定しての起動はOpenShift上のGUIから実行することもできます。コマンドラインで実行する場合に比べてさらにお手軽です。こちらの記事を参考にしてみてください。 qiita.com
Red Hatの小島です。 Amazon Web Services (以下、AWS)では非仮想化環境や独自のハイパーバイザーでのアプリケーション実行を希望するユーザーに対して、東京と大阪リージョンを含む様々なリージョンでのAmazon EC2上のベアメタルインスタンスの実行をサポートしています。こうしたベアメタルインスタンスのサポートを利用して、Red Hat OpenShift Service on AWS (ROSA) では、ROSA with Hosted Control Plane (以下、ROSA HCP) 上でのOpenShift Virtualizationを利用した仮想化環境の実行を、ROSA HCP ver.4.16からサポートするようになりました。ROSAでのOpenShift Virtualizationを利用すると、ユーザーは次のようなメリットを享受できるようになります。 移行ツールを利用した、既存VMware環境上の仮想マシンのAWSへの迅速な移行 オンプレミスとAWSのハイブリッドクラウドに対して、OpenShiftを利用したアプリケーション開発と運用の統一 AWSでの、OpenShift Virtualizationに含まれる無制限のRHELサブスクリプションの利用 従量課金制のAWSというクラウドの特徴を利用した、OpenShift Virtualizationの本格導入前検証やインフラ環境構築/拡張の簡単化 これらのメリットなどを記載したOpenShift Virtualization on ROSAに関するブログが、AWSのWebページでも公開されていますのでご参照ください。 aws.amazon.com 本記事では、ROSA HCPでのOpenShift Virtualizationの利用方法とそのポイントをご紹介します。 事前準備 ROSA HCPクラスターでのOpenShift Virtualizationのインストールと利用 Amazon FSx for NetApp ONTAPのファイルシステム作成 (補足) Multi-AZ構成時のAmazon FSx for NetApp ONTAPのファイルシステム作成 ROSA HCPクラスターへのNetApp Trident CSIドライバのインストールと設定 (補足) OpenShiftのOperatorHubを利用したNetApp Trident CSIドライバのインストール ストレージ仮想マシン(SVM)管理ユーザーとパスワードをROSA HCPクラスターに保存するためのシークレット作成 Amazon FSx for NetApp ONTAPのファイルシステムをTrident CSIのバックエンドとして設定 Amazon FSx for NetApp ONTAPのファイルシステムを利用したストレージクラスの作成 Amazon FSx for NetApp ONTAPを利用するためのインバウンドルールの追加 仮想マシンの作成 Red Hat Subscription Manager (RHSM)に自動登録するためのアクティベーションキーの作成と利用 カスタムテンプレートの作成 クリーンアップ まとめ 事前準備 ROSA HCPでのOpenShift Virtualizationを利用するには、次のリソースが必要になります。 ROSA HCPクラスター (ver. 4.16以降) クラスター作成に必要となるAWSアカウントやRed Hatアカウントなどの各種リソースを含みます。 AWSの Amazon FSx for NetApp ONTAP を作成および利用する権限 この共有ストレージは、後述するOpenShift Virtualizationでのライブマイグレーション用途として利用します。 ROSA HCPクラスターの作成方法については、下記のコンテンツをご参照ください。 rh-open.github.io ROSA HCPクラスターでのOpenShift Virtualizationのインストールと利用 ROSA HCPクラスターでのOpenShift Virtualizationは、通常のSelf-ManagedのOpenShiftと同じような方法でインストールと利用ができるようになっています。ただし、仮想マシンを実行するためにはベアメタルインスタンスが必要なので、ROSA HCPクラスターを作るとき、または、(ユーザーアプリケーションの実行ノードとなる)ワーカーノードを追加するときにインスタンスタイプをベアメタルタイプに指定する必要があります。ROSA HCPで利用可能なインスタンスタイプは下記をご参照ください。 metal という拡張子が付いている名前のインスタンスタイプがベアメタルとなります。 docs.openshift.com また、AWSリージョンごとに利用できるAmazon EC2のインスタンスタイプは下記をご参照ください。 docs.aws.amazon.com ROSA HCPクラスターにワーカーノードを追加/削除する方法については、下記のコンテンツをご参照ください。なお、ベアメタルインスタンスを追加する場合、大体30分ほどでワーカーノードの追加が完了します。 rh-open.github.io ROSA HCPクラスターにベアメタルインスタンスが追加されると、ROSA HCPクラスターのOpenShiftコンソールに cluster-admin などの管理者アカウントでログインして下記のような画面で確認できます。この構成ではデフォルトのワーカーノード(m5.xlarge)2台に加えて、ベアメタルのワーカーノード(c5n.metal)を2台追加しています。ROSA HCPクラスターは、ワーカーノードに利用されるvCPU数が増えるほど利用料金が増えるため、最安料金で試そうとなると2024年10月時点ではm5zn.metal (48 vCPU, 192 GiB)をワーカーノードとして利用することになりますが、本記事ではAWSの東京/大阪リージョンでも利用可能なc5n.metal (72 vCPU, 192 GiB) を利用しています。 ベアメタルインスタンスのワーカーノードを追加したら、あとはSelf-Managed OpenShiftと同じ方法でOpenShift Virtualizationが利用できます。OpenShiftコンソールのOperator HubからOpenShift VirtualizationのOperatorをデフォルトのパラメーターをそのまま利用してインストールします。 OpenShift VirtualizationのOperatorからHyperConvergedインスタンスを作成します。これも全てデフォルトのパラメーターのままで「作成」をクリックして、 kubevirt-hyperconverged という名前のHyperConvergedインスタンスを openshift-cnv プロジェクトに作成します。 数分待つと openshift-cnv プロジェクトにOpenShift Virtualization関連のPodが実行されて、OpenShiftコンソールに「Virtualization」という追加されたメニューから仮想マシンを作成できるようになります。「Virtualization」メニューの表示には、OpenShiftのWebコンソールを再読み込みする必要があります。ここで表示されているテンプレートのカタログから、Red Hat Enterprise Linux (RHEL) などの仮想マシンを作成できます。 Amazon FSx for NetApp ONTAPのファイルシステム作成 このまま仮想マシンを作成してもいいのですが、ROSAのデフォルトのストレージクラスとして利用されるAmazon EBSのgp3ボリュームでは複数のEC2インスタンスからの共有ストレージとして利用不可であり、またAmazon EFSは共有ファイルシステムとして利用できますが、OpenShift Virtualizationの仮想マシンの共有ストレージとして利用するために必要となる共有ブロックストレージとしての利用ができなくなっています。そのため、ベアメタルインスタンス間の仮想マシンのライブマイグレーションが利用できません。 そこで、同じくAWSがサポートしている、共有ブロックストレージとして利用可能なAmazon FSx for NetApp ONTAPの共有ストレージを作成して利用します。ここでは、Single AZに作成したROSA HCPクラスターからAmazon FSx for NetApp ONTAPの共有ストレージを利用することを前提とします。 ※ 本記事では以下の2つのブログを参考にしています。 aws.amazon.com cloud.redhat.com AWSのAmazon FSxコンソールにログインして、ROSA HCPクラスターを作成したリージョンと同じリージョンに移動します。最初はファイルシステムが作成されていない状態なので、「ファイルシステムを作成」をクリックして作成していきます。 ファイルシステムのオプションから「Amazon FSx for NetApp ONTAP」を選択して「次へ」をクリックします。 続いて「スタンダード作成」をクリックして、以下のようにファイルシステムの詳細情報を入力します。 ファイルシステムの詳細 デプロイタイプ: シングルAZ 2 SSDストレージ容量: 1024 GiB (最小値を指定) 残りのパラメーターはデフォルト値を利用 ネットワークとセキュリティ (これらの情報は、Amazon EC2のコンソールから確認可能) VPC: 「ROSA HCPクラスターを作成したVPC」を選択 VPCセキュリティグループ: 「ROSA HCPクラスターのワーカーノードが利用しているセキュリティグループ」を選択 サブネット: 「ROSA HCPクラスターのワーカーノードが利用しているサブネット」を選択 デフォルトのストレージ仮想マシン設定 ストレージ仮想マシン名: svm1 (任意の名前を指定可能) SVM管理パスワード: 「パスワードを指定」を選択して、任意のパスワードを指定 残りのパラメーターはデフォルト値を利用 これら以外のパラメーターはデフォルト値のままにしておいて「次へ」をクリックして、最後に「ファイルシステムを作成」をクリックします。 すると、大体10分ほどでファイルシステムの作成が完了します。 (補足) Multi-AZ構成時のAmazon FSx for NetApp ONTAPのファイルシステム作成 前述した手順では、ROSA HCPクラスターとAmazon FSx for NetApp ONTAPのファイルシステムの両方ともSingle-AZ構成であることを想定しています。これを両方ともMulti-AZ構成にする場合、Single-AZ構成時のAmazon FSx for NetApp ONTAPのファイルシステム作成手順に、「ファイルシステムの詳細」の「デプロイタイプ: マルチAZ 2」への変更に加えて、下記の変更を適用します。 ネットワークとセキュリティ (これらの情報は、Amazon EC2とAmazon VPCのコンソールから確認可能) VPC: 「ROSA HCPクラスターを作成したVPC」を選択 VPCセキュリティグループ: 「ROSA HCPクラスターのワーカーノードが利用しているセキュリティグループ」を選択 Multi-AZ構成の各ワーカーノードは、同じセキュリティグループを利用しています。 推奨サブネット: 「ワーカーノードが利用しているサブネット」を選択 スタンバイサブネット: 「ワーカーノードが利用しているサブネット」を選択 Multi-AZ構成のワーカーノードは、合計3つのプライベートサブネットを利用しているので、そのうち2つのサブネットを「推奨サブネット」「スタンバイサブネット」として選択します。 VPCルートテーブル: ワーカーノードが利用しているサブネットに紐付けられた3つのルートテーブルを全て選択 このサブネットは、Multi-AZ構成のワーカーノードが利用している3つのプライベートサブネットです。 残りのパラメーターはデフォルト値を利用 あとは、Single-AZ構成の時と同じ手順でファイルシステムを作成できます。 ROSA HCPクラスターへのNetApp Trident CSIドライバのインストールと設定 ここで作成したファイルシステムをROSA HCPクラスターから利用するために、Trident CSIドライバをインストールします。インストールにはROSA HCPクラスターのOpenShiftコンソールから利用できるWeb Terminalを、ROSA HCPクラスターの管理者アカウントで利用します。Web Terminalのインストールと利用方法については、下記のコンテンツをご参照ください。 rh-open.github.io Web Terminalが提供するコンソールを開いて、Trident CSIドライバのインストール先となる trident プロジェクトを作成します。 oc new-project trident 次にTrident CSIドライバをGitリポジトリからダウンロードして、内容を展開します。ここでダウンロードしているドライバは、2024年10月時点での最新バージョン(v24.06.1)のものです。 curl -L -o trident.tar.gz https://github.com/NetApp/trident/releases/download/v24.06.1/trident-installer-24.06.1.tar.gz tar xf trident.tar.gz 最後にhelmコマンドで、 trident プロジェクトにTrident CSIドライバをインストールします。STATUSが「deployed」になれば、インストールが完了しています。CSIドライバのインストール状態については、 helm status trident コマンドや helm get all trident コマンドでも確認できます。 cd trident-installer/helm/ helm install trident -n trident trident-operator-100.2406.1.tgz ...<snip>... NAME: trident LAST DEPLOYED: Tue Oct 22 02:40:41 2024 NAMESPACE: trident STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Thank you for installing trident-operator, which will deploy and manage NetApp's Trident CSI storage provisioner for Kubernetes. ...<snip>... To learn more about the release, try: $ helm status trident $ helm get all trident これらのコマンドをOpenShiftのWeb Terminalで実行した場合の画像が下記になります。 Trident CSIドライバのインストールが完了すると、Trident Operatorによって自動的に trident-node-linux という接頭辞が付いたPodがワーカーノードの台数分だけ作成されます。ワーカーノードを追加/削除すると、それに応じて trident-node-linux Podが自動追加/自動削除されます。下記の画像は、ROSA HCPクラスターのワーカーノード3台構成に、Trident CSIドライバをインストールした時の trident プロジェクトのPodの状態を表示したものです。 (補足) OpenShiftのOperatorHubを利用したNetApp Trident CSIドライバのインストール OpenShiftのOperatorHubにもTrident CSIドライバをインストールするためのOperatorのカタログがありますので、helmコマンドでなく、OperatorHubのカタログを利用してTrident CSIドライバをインストールすることもできます。 OperatorHubのカタログから、「trident」を入力して「Astra Trident」Operatorを選択して、「インストール」をクリックします。 Astra Trident Operatorのインストール画面では、「インストール済みのnamespace」で「trident」プロジェクトを選択します。「trident」プロジェクトを作成していない場合は、「プロジェクトの作成」から「trident」プロジェクトを作成してください。そして「インストール」をクリックしてAstra Trident Operatorをインストールします。 Astra Trident Operatorのインストール完了後に、「Trident Orchestrator」インスタンスを作成します。下記の画面の「インスタンスの作成」をクリックして、あとはデフォルトのままで「作成」をクリックします。 「Trident Orchestrator」インスタンスの作成が完了すると、「trident」プロジェクトに前述した trident-node-linux Podが作成されていることを確認できます。 ストレージ仮想マシン(SVM)管理ユーザーとパスワードをROSA HCPクラスターに保存するためのシークレット作成 Amazon FSxのファイルシステムを作成するときに指定したSVM管理パスワードを、ROSA HCPクラスターから利用するためのシークレット backend-fsx-ontap-nas-secret を trident プロジェクトに作成します。OpenShiftのコンソールの右上にある「+」アイコンをクリックして、下記のYAMLファイルを入力して「作成」をクリックします。 apiVersion: v1 kind: Secret metadata: name: backend-fsx-ontap-nas-secret namespace: trident type: Opaque stringData: username: vsadmin password: <SVM管理パスワードを指定> Amazon FSx for NetApp ONTAPのファイルシステムをTrident CSIのバックエンドとして設定 Amazon FSxのコンソールから、作成したSVMの「管理IPアドレス」と「NFS IPアドレス」「名前」を確認します。下記の画像では「10.0.0.124」と「svm1」となります。 確認したIPアドレスをもとに、バックエンド設定用のyamlファイルをOpenShiftのコンソールから入力して作成します。下記の「managementLIF」「dataLIF」「svm」については、それぞれご自身が作成したSVMの「管理IPアドレス」「NFS IPアドレス」「SVMの名前」に置き換えて下さい。 apiVersion: trident.netapp.io/v1 kind: TridentBackendConfig metadata: name: backend-fsx-ontap-nas namespace: trident spec: version: 1 backendName: fsx-ontap storageDriverName: ontap-nas managementLIF: 10.0.0.124 # SVMの管理IPアドレス dataLIF: 10.0.0.124 # SVMのNFS IPアドレス svm: svm1 # SVMの名前 credentials: name: backend-fsx-ontap-nas-secret これでバックエンドとしての設定が完了です。次のコマンドを実行して、「PHASE: Bound」「STATUS: Success」となっていればバックエンド設定が無事に完了していることを確認できます。 oc get tbc -n trident NAME BACKEND NAME BACKEND UUID PHASE STATUS backend-fsx-ontap-nas fsx-ontap 53c2b404-5c7c-4c86-a649-a5816f6334d5 Bound Success Amazon FSx for NetApp ONTAPのファイルシステムを利用したストレージクラスの作成 バックエンドの設定が完了したあとに、コンテナの永続ボリュームとして利用するためのストレージクラスを作成します。OpenShiftのコンソールから「StorageClasses」メニューを選択して、 trident-csi という名前のストレージクラスを作成します。「回収ポリシー」と「ボリュームバインディングモード」は何を選択してもいいですが、この例では「保持」と「即時」を選択しています。 「プロビジョナー」は「csi.trident.netapp.io」を選択して、追加パラメーターとして「backendType: ontap-nas」を入力します。この「ontap-nas」はバックエンド設定時に指定した「storageDriverName」の名前となります。そして、「作成」をクリックしてストレージクラスを作成します。 また、仮想マシンのテンプレートカタログから仮想マシンを作成する際に簡単に利用できるようにするために、ここで作成したストレージクラスをデフォルトのストレージクラスに変更※します。ROSA HCPクラスターのデフォルトのストレージクラスはAmazon EBSのgp3ボリュームを利用するように自動設定されているので、この gp3-csi ストレージクラスを選択してYAMLファイルを以下のように修正して保存することで、 gp3-csi ストレージクラスをデフォルトから外すことができます。 ※ 仮想マシンを作成する際に、YAMLファイルからストレージクラスを指定することもできるので、ストレージクラスのデフォルト化は必須ではありません。 storageclass.kubernetes.io/is-default-class: 'true' -> storageclass.kubernetes.io/is-default-class: 'false' そして、 trident-csi ストレージクラスをデフォルトにするために、YAMLファイルを以下のように修正して保存します。 annotations.storageclass.kubernetes.io/is-default-class: 'true' をYAMLファイルに追加 これで trident-csi ストレージクラスをデフォルトに設定することができました。 ここまで紹介しましたNetApp TridentをOpenShiftから利用する情報の詳細については、NetAppのドキュメントもご参照ください。 docs.netapp.com また、Amazon FSx for NetApp ONTAPを利用していてNetApp Tridentについて問い合わせをしたい場合、AWSのサポートケースを利用できます。サポートケースを作る際に、「Trident」カテゴリーを選択してください。必要に応じて、AWSサポートチームからNetApp社にエスカレーションされる仕組みになっています。 Amazon FSx for NetApp ONTAPを利用するためのインバウンドルールの追加 ROSA HCPクラスターのワーカーノードからAmazon FSx for NetApp ONTAPのファイルシステムを利用するためのインバウンドルールを、ワーカーノードが利用しているAmazon EC2のセキュリティグループに追加する必要があります。ROSA HCPクラスター作成時に指定したワーカーノードの「Machine CIDR」(下記の画像ではデフォルトの10.0.0.0/16を指定)からのアクセスを許可しないと、ファイルシステムが利用できないようになっています。下記のAWSドキュメントにあるインバウンドルールを参照しながら、Amazon EC2のコンソールまたはAWS CLIを利用して追加していきます。 docs.aws.amazon.com セキュリティグループのインバウンドルールを追加すると、下記のような画像になります。この変更を保存します。 仮想マシンの作成 ここまでくれば、あとはSelf-Managed OpenShiftと同様に仮想マシンを作成したり、ライブマイグレーションしたりすることができます。ROSA HCPクラスターにローカルユーザー(下記の画像では testuser20 )で再ログインして、適当なプロジェクト(下記の画像では test-project20 )を作成したあとに、仮想マシンのテンプレートカタログからRHEL9の仮想マシンを作成してみます。「Red Hat Enterprise Linux 9 VM」をメニューから選択して、パラメーターはデフォルトのままで「Quick create VirtualMachine」をクリックして作成します。 OpenShift Virtualizationのインストール時に自動作成された openshift-virtualization-os-images プロジェクトにある、PVCのゴールデンイメージからデータをコピーした後に、RHEL9の仮想マシンが実行されて「Console」タブからVNCコンソールにアクセスできます。また、画面右上にある「Actions」から「Migrate」をクリックすることで、ベアメタルインスタンス間でのライブマイグレーションも数秒ほどで実行できます。 Red Hatが提供するゴールデンイメージの詳細については、下記をご参照ください。 docs.redhat.com Red Hat Subscription Manager (RHSM)に自動登録するためのアクティベーションキーの作成と利用 ROSA HCPで利用可能なOpenShift Virtualizationには、RHELの仮想マシンを無制限に実行できる権限が付与されます。デフォルトのRHELのテンプレートだと、Red Hat CDNのRHELリポジトリを利用したい場合、RHEL仮想マシン作成後にsubscription-managerコマンドでRHSMにシステム登録をする必要があります。このシステム登録には、ROSA HCPクラスター作成時に利用したRed Hatアカウントを利用してください。また、RHSMを利用するにいたって、ROSA HCPクラスターのプライベート化などによる送信トラフィック制限がある場合、次のホスト名とポートを許可してください。 subscription.rhn.redhat.com:443 [https] subscription.rhsm.redhat.com:443 [https] cdn.redhat.com:443 [https] *.akamaiedge.net:443 [https] *.akamaitechnologies.com:443 [https] access.redhat.com RHEL仮想マシン作成後のRHSMへのシステム登録を自動化することもできます。この時、RHELシステムを登録するためのアクティベーションキーを、Red Hat Hybrid Cloud Consoleのコンソールから作成して利用することになります。 最初に、ROSA HCPクラスター作成時に利用したRed Hatアカウントで下記のURLにアクセスします。 https://console.redhat.com/insights/connector/activation-keys すると次のような画面が表示されすので、ここからアクティベーションキーを作成します。この時表示されるRed Hatアカウントの「Organization ID」もメモしておいて下さい。「Create activation key」をクリックします。 アクティベーションキー作成画面に移りますので、任意の名前(下記画像では「activation-key01」)、Select Workloadでは「Extended support releases」とRHELのバージョンとなる「9.4」を選択します。これによって、アクティベーションキーを利用したRHELシステム登録後に、RHEL9のマイナーリリースの延長サポートであるExtended Update Support (EUS)のリポジトリを自動的に使えるようになります。ここで「Latest release」を選択した場合、RHELの最新マイナーリリースのリポジトリだけを使えるようになります。なお、アクティベーションキーでRHELシステムを登録した後も、RHELリポジトリの参照設定は自由に変更できます。 Roleは「RHEL Server」、SLAとUsageは適宜選択します。下記画像の例ではROSAのサポートレベルであるPremium(24時間365日サポート)に沿って「Premium」と「Production」を選択しています。これらの情報を確認した後に「Create」ボタンを押してアクティベーションキー「activation-key01」を作成します。 アクティベーションキーには、複数のRHELのメジャーリリースのリポジトリを紐づけることもできます。「Add repositories」をクリックしてRHEL8のEUSリポジトリを追加できます。これによって、このアクティベーションキーを利用してRHEL8とRHEL9のシステムを登録すると、RHEL8とRHEL9の最新マイナーリリースのリポジトリとEUSリポジトリの両方が最初から利用できるようになります。 作成したアクティベーションキーをテンプレートから利用するために、ROSA HCPクラスターの管理者アカウントでOpenShiftコンソールにログインして、「Virtualization」→「Overview」→「Settings」からアクティベーションキーの名前とOrganization IDを入力して「Apply」をクリックします。これによって、RHEL仮想マシンを作成するためのテンプレートから仮想マシン作成時に、自動的にアクティベーションキーによるシステム登録とリポジトリ有効化が実行されます。 実際に「Red Hat Enterprise Linux 9 VM」テンプレートからRHEL9仮想マシンを作成すると、cloud-initのポストスクリプトによるRHSMへの自動登録が実行されて、事前に設定したRHEL9とRHEL9のEUSリポジトリを最初から参照して、パッケージのインストール/アップデート/削除ができるようになっていることを確認できます。 カスタムテンプレートの作成 前述した手順で作成したアクティベーションキーを、特定のテンプレートだけに利用させるようなカスタムテンプレートを作成することもできます。カスタムテンプレート作成には、OpenShift Virtualization Operatorによって元々用意されているテンプレートをベースにします。RHEL9仮想マシンを作成するテンプレートだと、 rhel9-server-small という名前のテンプレートが openshift プロジェクトに用意されているので、このテンプレートのYAMLファイルを次のコマンドで表示します。 oc get template rhel9-server-small -n openshift -o yaml apiVersion: template.openshift.io/v1 kind: Template metadata: annotations: defaults.template.kubevirt.io/disk: rootdisk description: Template for Red Hat Enterprise Linux 9 VM or newer. A PVC with the RHEL disk image must be available. ...<snip>... 表示されたYAMLファイルの情報をコピーして、「Templates」メニューから「Create Template」ボタンを作成することで表示されるテキストボックスに貼り付けます。この時、下記の修正を適用して「作成」をクリックしてカスタムテンプレートを作成します。 openshift.io/display-name: Subscribed Red Hat Enterprise Linux 9 VM に修正 template.kubevirt.io/type: vm に修正 name: subscribed-rhel9-server-small に修正 namespace: test-project20 に修正 vm.kubevirt.io/template: subscribed-rhel9-server-small に修正 cloudInitNoCloud.userData の箇所に、rh_subscriptionの情報を追加 これらの修正をピックアップしたYAMLファイルは以下のようになります。 apiVersion: template.openshift.io/v1 kind: Template metadata: annotations: ...<snip>... openshift.io/display-name: Subscribed Red Hat Enterprise Linux 9 VM ...<snip>... template.kubevirt.io/type: vm ...<snip>... name: subscribed-rhel9-server-small namespace: test-project20 ...<snip>... vm.kubevirt.io/template: subscribed-rhel9-server-small ...<snip>... - cloudInitNoCloud: userData: |- #cloud-config user: cloud-user password: ${CLOUD_USER_PASSWORD} chpasswd: { expire: False } rh_subscription: activation-key: activation-key01 # アクティベーションキーの名前 org: <Red HatアカウントのOrganization IDを指定> name: cloudinitdisk ...<snip>... そして「作成」ボタンをクリックして、カスタムテンプレートを test-project20 プロジェクトに作成します。作成後は「Subscribed Red Hat Enterprise Linux 9 VM」という名前のテンプレートが利用できるようになっています。このカスタムテンプレートからRHEL9仮想マシンを作成すると、RHSMへの自動登録が実行されます。 OpenShift Virtualizationについての他の操作を試してみたい場合、下記の連載記事の第4回や第5回も併せてご参照ください。 rheb.hatenablog.com rheb.hatenablog.com クリーンアップ ROSA HCPでのOpenShift Virtualization環境を消去したい場合、ROSA HCPクラスターの削除とAmazon FSx for NetApp ONTAPのファイルシステム削除を実行してください。ROSA HCPクラスターの削除は、 rosa delete cluster コマンドなどで実行できます。下記は rosa-hcp-01 という名前のROSA HCPクラスターを削除するコマンドの例です。 rosa delete cluster -c rosa-hcp-01 --yes ROSA HCPクラスターの削除については、下記のWebページにある「ROSA HCPクラスターの削除」の項目もご参照ください。 rh-open.github.io まとめ このように、ROSA HCPクラスターではOpenShift Virtualizationを簡単に実行して、従量課金制で試してみることができます。OpenShift Virtualizationを試してみる際に、検証用マシンなどを用意するハードルが高い場合は、ぜひROSA HCPクラスターでのご利用をご検討ください。