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

TECH PLAY

Red Hat  - Open Innovation Labs

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

全900件

Red Hatのソリューションアーキテクトの杉本です。 Red Hat にはクラウドネイティブアプリの開発に役立つ、Application Services のラインナップが充実していることをご存知ですか? ここでは、Red Hatの Application Services に関する注目ニュースを、各製品技術に特化したソリューションアーキテクトが、ご紹介します。 今回は 2021/1 月号となります。 想定読者 エンタープライズアーキテクト アプリケーション開発者 システムの提案をするSIerの方 特集1: ”クラウドネイティブアプリケーション開発の基盤” Red Hat Runtimesのご紹介 ビジネスの機敏性の向上、高可用性、開発効率性の向上など様々な要件からクラウドネイティブアプリケーションを導入することが増えてきました。今回はクラウドネイティブアプリケーション開発の基盤となるRed Hatの Runtimesという製品群についてなぜこの様な製品群が必要なのかと言う背景から製品群に含まれる各製品について簡単に紹介しています。 speakerdeck.com 特集2: API管理/イベント駆動アーキテクチャ/データ連携/サーバーレス/サービスメッシュなど、"インテグレーション"に必要な機能を網羅するRed Hat Integrationの全体像をご紹介 Red Hatのミドルウェア製品である Red Hat Integration は3scale/Fuse/AMQをまとめた製品となり、製品機能としても"インテグレーション"に関わる多様な機能を含んでいます。デジタルトランスフォーメーションを進める上では、新規に開発するマイクロサービスだけではなく既存システムとの連携も考慮する必要があります。この資料ではそんなRed Hat Integrationの機能をまとめて紹介しています。 speakerdeck.com 特集3: 業務でのステータス管理の重要性 アプリケーションの中で結構厄介な、「業務のステータス」は皆さんどのように実装・管理していますか?ロジックのスパゲッティ化の一つの原因ともなっている、「業務ステータス」の実装について考察してみます。 rheb.hatenablog.com 好評開催中!クラウドネイティブアプリ開発関連のWebinar全6回 Cloud Nativeを見据えたアプリケーションアーキテクチャとレガシーモダナイゼーション コンテナ時代の開発ツールチェインと開発プロセスのベストプラクティス クラウド/コンテナを前提とした時代のアプリケーション実行環境の選択 マイクロサービス/サーバーレス実践入門 これからのシステム連携を実現するデジタル基盤とアプローチ Cloud Nativeなデータパイプラインの作り方とオープンハイブリッドクラウドへの展開 各回とも、オンデマンドで視聴出来ます。(お名前とメールアドレス等の登録のみで視聴可能です) 下記リンクよりぜひご登録ください。 www.redhat.com 直近GAになった製品群 最近リリースとなった Application Services 製品群のリストをご紹介します。 見逃している製品が無いか、是非一度ご確認ください。 Red Hat AMQ Stream 1.6 Red Hat AMQ Broker 7.8
この記事は Brendan Conoboy による How RHEL is Made の翻訳です。 今週、Red HatはCentOS Stream 8に全力を注ぐ計画を発表し、その結果、1年後にはCentOS Linux 8が廃止されることになりました。 CentOS Streamはもともと2019年9月に発表されたもので、開発や検証が進むとすぐにアップデートを提供するRHELの継続的なリリースです。 現在CentOS Linuxを使用している多くの人は、CentOS Stream 8が自分の使用に適したディストリビューションになるのかどうか、テストされているのか、安定しているのか、などを疑問に思っています。 CentOS Stream に何が期待できるかを知るには、Red Hat Enterprise Linux がどのように構築されているかを知ることが一番の出発点となります。 それでは、さっそく始めましょう! Red Hatは長い間Linuxのリリースを行っており、そのオリジナルの開発方法は アジャイルマニフェスト よりも前から行われています。 歴史的に、RHELは閉鎖されたグループにより構築されており、その計画はクローズドでした。RHEL 8のローンチ時に発表された、予測可能な6ヶ月毎のマイナーリリース/3年毎のメジャーリリースの発表でさえ記念碑的な情報公開と思えるほどでした。 幸いRed HatのLinuxディストリビューション開発方法は、 前世紀に始まった時から進化したというだけでなく、ちょうど18ヶ月前にRHEL 8が発表されて以来、既に複数世代のプロセス改善が行われています。 アップストリーム・ファースト、莫大な品質エンジニアリング、エコシステムパートナーシップ、カスタマーケアなどの基本的なことは変わりませんが、これらの基本的なことがらの実装を改善するために継続的に取り組んでいます。 基本からはじめましょう。すべてのRHELマイナーリリースは、前のリリースをベースにして、アップストリーム開発のバックポートを追加します。 しばしば、Red Hatter自身がこれらのパッチのオリジナルの作成者ですが、近道はありません。最終的なリリースへパッチの統合作業を開始する前に、すべてのパッチがアップストリームに受け入れられる必要があり、これは最初のテストになります。 しかし、アップストリームにパッチが存在するだけでは製品へのパッチの組み込みは保証されません。 RHELにアップストリームの変更を導入する決定は、チームの決定であり、チームは大規模です:開発者、品質エンジニア、サポート担当者、プロダクトオーナー、および様々なパートナーが、優先順位と実現可能性について一緒に作業します。 一旦、決定に達し、コミットメントがなされると、開発者と品質エンジニアはコードを書き始めます。 ご存知のように、最も和気藹々としたライバル関係の中で、開発者は誰にも壊すことのできないコードを書こうとし、品質エンジニアは開発者の書いたコードを壊す一連の方法を作成します。 ここで Red Hat が投資している 2 番目の重要な領域は、テストです。 ユニットテスト、システムテスト、カーネルと ユーザースペースの ABI 適合性テスト、パフォーマンステスト、依存関係テスト、アーキテクチャテスト、ドライバーテスト、負荷テストなど、多数のテストを行っています。 テストを持つことは基本的なことですが、応用することで意味をもたらします。 ここで、Red Hat が投資する 3 番目の重要な領域、プロセスインフラストラクチャについて説明します。 Red Hat は過去数年間、一連の「 Always Ready 」オペレーティングシステムに取り組んできました。 その目標は、名前の通り「いつでもOSをリリースする準備ができている」ということです。 これは、言うは易し行うは難しです。複雑なシステムでは、多くのことが意図しない結果をもたらす可能性があります。 この問題を処理するために、私たちは自動化のレイヤーを使用し、変更への信頼性を徐々に高め、それらが統合されてディストリビューションにリリースされるようにしています。 ここでは、RHELのすべての変更がRHELに含まれる前に通過する必要があるプロセスについて、ハイレベルな概要を示します。 変更がRHELを対象としている場合、実際にRHELに含まれる前に、複数の段階的なステップが発生します。 変更はビルドされますが、唯一の確かな結果は、CIシステムがそのビルドで一連のテストを実行することです(ビルドは、まだ一般には利用できません)。 これらのテストに合格した場合、コード変更に特化した事前検証の第二ラウンドが行われます (まだ十分ではありません)。 そして、これらのテストに合格した場合、その変更は暫定的にエラッタシステムに含まれ、さらなる検証の対象となります (まだ公開する準備はできていません)。 体系的なテストスイートが、全体的な機能検証をするため、結合された全体に対して実行されます。 そして、これらのテストに合格した場合にやっと、CentOS Stream システムから利用可能なアップデートとして認識される場所へ、このビルドが組み込まれることになります。 これは長いパイプラインであり、毎日多くの変更が行われています。 このシステムのビジョンやアーキテクチャに興味のある方は、「 CentOS Streamは継続的デリバリーです 」を読んでください。 このシステムの説明はエレガントで安心感があるように見えるかもしれませんが、実際に動いているのを見ていると全く逆のことを感じるかもしれません。テストが行われれば行われるほど、より多くのバグが発見され、Red Hatは大量のテストを行います。 歴史的に、RHELの開発は、閉鎖されたグループで行われ、人々を日常的なバグの特定と修正プロセスから隔離し、最終的な結果だけを世間に見せるようにしてきました。 将来的には、RHEL 9に近づくにつれてRHELの開発がより透明性を増して、このプロセスが不安を覚えるほどに可視化されてくるでしょう。 テストシステムは、そのような失敗がエンドユーザに届かないように構築されていますが、より深く覗き込むと、オペレーティングシステムの開発が非常に厄介なことに驚くかもしれません。 最後に、これらすべてのことがどれくらいでCentOS Streamに反映されるのか疑問に思っている人に、良いニュースがあります:それは、RHEL 8.4とCentOS Stream 8ですでに今日行われています。 RHELのビルドが検証されると同時に、CentOS Streamにも配信されます。 もちろん、まだ完全ではありません。CentOS StreamはRHELの周りに開発者コミュニティを創るという、そのミッションをまだ実現していません。Red Hatと関わり、将来のRHELを形作るためのより多くの選択肢がある目標へ向かっている途中です。 より良いテストから将来のコラボレーションにおける多くの側面まで、常に改善の余地があります。RHELの構築を共有することで、あなたとともに、そしてあなたのためにより良いOSを構築していきます。
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 Handling paginated APIs with Mutiny の翻訳記事です。 Mutiny の冒険の最初の方で、友人のアレックスが面白い問題を抱えてやってきました。アレックスは、REST サービスからリアクティブ的にデータを取得したいと考えていました。これまでのところ、問題はありません。このために必要なものはすべて私たちの道具箱に入っています。しかし、このサービスは、多くのサービスと同様に、ページ分割を利用しています。ああ!そうすると少し辛くなるんですよね。アレックスは全てのアイテムを取得して、ストリームとして処理したかったのです。ですが、一括では取得できません。ページごとにサービスを起動し、アイテムを抽出して、ストリームに入力する必要があります。 では、どうやってリアクティブに実現し、正気を失わずに適切なアイテムのストリームを構築するのでしょうか?見てみましょう! Punk API まずはAPIが必要です。アレックスが紹介してくれたのは、ビールを取得するための REST API である Punk API です。それはそれで楽しいし、さらに良いことに、ページ分割を使用しています。APIを手に入れた! https://api.punkapi.com/v2/beers?page=1 を呼び出すと、以下のようなJSON 配列が得られます。 [ { first beer } , { second beer } , // ... ] 私は、各オブジェクトの内容を議論することはしません。ですが、ドキュメントのページでは、そのことについて素晴らしい仕事をしています。ページ分割の側面に注目してみましょう。最初に、 page クエリパラメータを渡しました。これはどのページが欲しいかを示します。一般的に、ページを取得する際に、API は次のページがあるかどうかを知る方法を提供しています(JSONドキュメント内の特別なフィールドやHTTPヘッダ)。ですが、Punk API ではヒントを提供していません。だから、すべてのビールを取得するには、1,2,3.. ページ目のサービスを呼び出す必要があります。 これは、返されたJSON 配列が空になるまで呼び出します。 命令的な世界では、すべてのビールを取得するために、あなたはこのようなことをするでしょう。 List<Beer> beers = ... ; int page = 1 ; List<Beer> batch = ... do { batch= getBeersFromPage(page); beers.addAll(batch); page = page + 1 ; } while (! batch.isEmpty()); リアクティブで同じことを実現し、ビールのストリームを作るにはどうすれば良いでしょうか? 一歩ずつ進めていきましょう。 単一ページの取得 まずは、1つのページを取得する方法を見てみましょう。今回は Vert.x Web Client を使いますが、Mutiny API を提供しているリアクティブな HTTP クライアントであれば何でも使えます。 // クライアントを作成 WebClient client = WebClient.create(vertx, new WebClientOptions() .setDefaultHost( "api.punkapi.com" ) .setDefaultPort( 443 ) .setSsl( true ) ); // 最初のページを取得 Uni<List<Beer>> uni = client.get( "/v2/beers?page=1" ) .send() .onItem() .transform(Pagination::toListOfBeer); このスニペットは Web クライアントを作成します。そして、そのクライアントを使って、最初のページを取得します。 結果( onItem )を受け取ると、JSON 配列をビールのリストに変換します。 このコードをメソッドで抽出して、ページ番号をパラメータにしてみましょう。 private static Uni<List<Beer>> getPage(WebClient client, int page) { return client.get( "/v2/beers?page=" + page) .send() .onItem() .transform(Pagination::toListOfBeer); } ここまでは順調です。 複数のページを取得 というわけで、1 ページを取得してそこから項目を抽出する方法がわかりました。この操作をページごとに繰り返し、ストリームを提供するだけです。 Mutiny は Uni を複数回繰り返すことで Multi を作成するメソッドを提供しています。その内部では、 Uni を返すメソッドを呼び出して、その上でサブスクライブしています。しかし、私たちは進みながら、今のページを受け渡す必要があります。Mutiny は、 Uni を作成するメソッドにページ番号をインクリメントさせるために、状態を保存する可能性を提供します。 Multi.createBy() .repeating() .uni(AtomicInteger:: new , page -> getPage(client, page.incrementAndGet()) ) 上記のコードでは、 getPage メソッドで返された Unis によって、出されたアイテムを持つストリームを作成しています。ページ番号( AtomicInteger に格納されている)を毎回インクリメントしています。だから、それは1、2、3... ページを取得します。そして、毎回受信した List<Beer> を下流に放出します。 しかし、どこかの時点で止めなければなりません。先ほども言いましたが、返されたリストが空になったときに停止できます。 Multi<List<Beer>> multi = Multi.createBy() .repeating() .uni(AtomicInteger:: new , page -> getPage(client, page.incrementAndGet())) .until(List::isEmpty); until 句は、いつ反復を停止しなければならないかを示します。取得したリスト( getPage で生成されたリスト)を受け取り、このリストが空の場合は繰り返しを停止します。リストにビールが含まれている場合は、次のページを取得します。 ビールの開梱 私たちは今、リストのストリームを持っており、各リストにはビールのセットが含まれています。もうすぐだが、アレックスがビールのストリームを欲しがっている。だから、ビールを開梱しないといけない。 これを実現するための最初のアプローチは、 transformToMultiAndConcatenate を使用します。つまり、各リストに含まれるビールを含む新しい multi を作成し、これらの multis 連結します。 Multi<Beer> multi = Multi.createBy().repeating() .uni(AtomicInteger:: new , page -> getPage(client, page.incrementAndGet())) .until(List::isEmpty) .onItem() .transformToMultiAndConcatenate(l -> Multi.createFrom().iterable(l)); 連結 について疑問に思ったことはありますか? 他のブログ記事 もチェックしてみてください これは一般的な操作なので、Mutiny は全く同じことを行う disjoint メソッドを提供します。 Multi<Beer> multi = Multi.createBy().repeating() .uni(AtomicInteger:: new , page -> getPage(client, page.incrementAndGet())) .until(List::isEmpty) .onItem() .disjoint(); これで終わりです! リアクティブのメリット 私たちは私たちのストリームを持っています、今はそれを使用する時間です!それでは例として、説明文に「IPA」(流行に乗ろう)と書かれているビールの最初の 10 種類を検索してみましょう。 multi.transform() .byFilteringItemsWith(beer -> beer.description.contains( "IPA" )) .transform() .byTakingFirstItems( 10 ); 私たちのストリームの利点は、すべてのページを取得しないことです。十分なビールが手に入るととすぐにその繰り返しを止めます。どうやって?なぜならば、上流にアイテムを増やす必要がないことを伝え( キャンセル )、その繰り返しを止めるからです。このようにしてページ分割された API からアイテムを取得することで、リクエストの数を減らせます。その結果としてリモートサービスの負荷を減らせます。 喉が渇きました? このコードを試してみたい方は、この gist をチェックしてみてください。jbang ですぐに実行できます。 jbang https://gist.github.com/cescoffier/18a326a5c057392bec54d95ec5a06ca6
この記事はStef Walterによる CentOS Stream is Continuous Delivery の翻訳です。 継続的デリバリーの基礎:難しいことを継続的に行い、簡単になるようにする。 外から見ると、RHEL(そしてCentOS Linuxコンテンツ)を構築する方法は、この10年間で変わっていないように見えるかもしれません。しかし、その内部ではRHELを開発する方法について、顧客に影響を与えることなく記念碑的な変革を成し遂げようとしています。 私は様々なカンファレンスでこの話をしてきましたが、CentOS Linux 8とCentOS Streamについての発表は、ここで話をするきっかけを与えてくれました。 3年前、RHELエンジニアリングで働いている私たちの何人かはアイデアを持っていました:継続的インテグレーション、継続的デリバリー、予測可能なリリース頻度などの現代的な開発プラクティスを、早期リリースの頻繁なリリース、プルリクエスト、フォーク、コードレビューなどのオープンソース開発プラクティスと組みあわせてRHELに適用したらどうだろうか……。 明白でしょう? ……いえいえ。 Linuxディストリビューションは継続的インテグレーションとデリバリの壮大な挑戦 私をオープンソースに引き込んだのは、常にこのインテグレーションの課題でした。連携の取れていないプロジェクトが無限にあります。これは本当に驚くべき進化の例です。目を凝らしてみつめれば、奇妙な生物、突然変異、小宇宙、自然淘汰のすべてが目の前で起こっているのがよくわかります。 過去20年間、私は 100以上の異なるプロジェクト に貢献してきました。私の貢献は、ユーザーが首尾一貫した体験を持てるように、プロジェクトをシームレスに機能させることに重点を置いていました。 Cockpit プロジェクト はその最も目に見える例です。私たちは、それぞれが別々に開発され、10以上の異なるディストロで異なるスケジュールでリリースされた約95のLinux APIとコンポーネントを、首尾一貫したユーザーエクスペリエンスに統合し、6年以上にわたって隔週で安定したリリースを提供してきました。 Linuxが継続的インテグレーションとデリバリーの壮大な挑戦であるとすると、私はRHELを他に類を見ない絶対的な挑戦として見ています: 1万の調整されていないプロジェクト、数千人の貢献者、追加の構造( kABIのような )と追加の保証( 10+3年間のハードウェアイネーブルメント のような)を加えて、それらを継続的にインテグレーションし、毎日安定したリリースを配信するということです。 夢見るような目(まあ、涙目)で、私たちはその活動を「 Always Ready RHEL 」と呼びました。 この取り組みは、何千ものパッケージを継続的インテグレーションに丹念に組み込むことから始まりました。2017年の時点で、すべてのRHELコンポーネントのCIがまだなかったことに、多くの人がショックを受けました。しかし、もし簡単なことであれば、はるかに早くに実現していたでしょう。 今日では、RHELに入るすべての更新は、継続的インテグレーションのゲーティングを通過しなければ、コンポーネントの自動テストを実行するナイトリー構成に組み込まれません。そして、各変更は、RHELのナイトリービルドに含まれる前に、(主に品質エンジニアリングによって)RHEL品質であることを明示的に検証される必要があります。 「Always Ready RHEL」の取り組みは、今ではCentOS Streamとして知られている継続的デリバリーで続いています。RHELのナイトリー構成は、すでにCentOS Streamで配信されています。継続的デリバリーの全体的なポイントは、各リリースを前のリリースと同じように安定したものにすることです。私たちは毎日配信しています。 もう十分ですか?……いえいえ。 素人目には、CentOS Streamはすでに RHEL と同じくらい安定しています。 しかし、この挑戦は他に類を見ないものであり、RHELエンジニアはそのことを認識しています。それぞれのチームが作業をRHELへ統合する方法は、上流のコミュニティと同じくらい多様です。しかし、非常に多くの人々がこの目標の異なる側面について一緒に活動しているので、継続的デリバリーを現実のものにすることができると確信しています。 Fedora, CentOS Stream, RHELデリバリ Diagram licensed CC-SA: https://creativecommons.org/licenses/by-sa/4.0/ 8と9のデリバリーの流れはこのようになっています: 左側にFedoraのリリースを見ることができます。この図は、CentOS StreamがRHEL X.Yリリースの作業と同義であることを示しています。技術的に言えば、CentOS StreamとRHELのアップデートは、同じソースからビルドされた2つのバイナリパッケージです。更新は、RHELのナイトリービルドに公開される場合に限り、CentOS Streamに公開されます。したがって、RHEL のナイトリービルドは、あなたが取得する CentOS Stream アップデート そのものです 。いったんFedoraから分岐すると、私たちは、それぞれの変更が以前に行ったすべてのものの上にきれいに統合されるように開発を進めます。更新は、RHELの未発表のマイナーアップデートに公開された場合にのみ、CentOS Streamにプッシュされます。RHELの顧客は、後にこれらのそれぞれを RHEL Errataアップデート として見ることになります。 これらの変更のそれぞれは、バグ修正であれ、機能拡張であれ、CentOS Streamに到着する前に、自動テストでテストされ、品質エンジニアリングのプロセスで検証されます。 Streamで直接、そしてすぐに見えない唯一の作業は、すでにリリースされているRHELのマイナーバージョンに対する作業です(図では「errata」と表示されています)。多くの場合、この作業は、NDAの下で行われたり、(未公開の脆弱性のため)公開が禁止されていたり、あるいは、既にCentOS Streamに含まれている変更点のバックポートとなっています。 CentOS Stream は、RHEL と同程度の安定性を意図しています。継続的デリバリーの基本ですね。 しかし、RHELとしてリリースされた製品でさえ、完全に安定しているわけではありません。7月に、RHEL (およびCentOS) の「 boot hole 」脆弱性の修正は、 CVEそのもの よりもはるかに悪い結果となりました: 多くの システムが起動しない 原因となりました。酷いことです。 結果として、私たちは上流のコンポーネントの再構築に時間を投資しているだけでなく、このようなことが二度と起こらないようにプロセスを適応させています。直して、繰り返します。 私はCentOS Linux 8のEOLの決定には参加していませんでしたが、CentOS Streamの実現に向けて努力しています。これは、RHELをオープンソースにするためです。エコシステム全体と協力して、このエキサイティングな継続的インテグレーションとデリバリーの課題に取り組むことができる場とするためです。 製品をオープンソース化するのは難しいことですが、私たちは驚くべき進歩を遂げてきました。これまでのところ、 RHELの開発プロセスをFedoraと連携させ 、 RHELのすべての実際のソースを読みとり可能な場所に配置し 、 貢献者がRHELのどの部分に対してもプルリクエストを開くことができるようにし 、 早期かつ頻繁にリリースしました …… そして、これはほんの始まりに過ぎません。期待どおりのタイミングでRHELのリリースを提供し続けつつ、何百人もの人がこのCentOS Streamという変化に取り組んでいます。 CentOSストリームは、安定した、信頼性の高い、RHELの継続的デリバリーです。
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 Wipro Addresses Seismic Shift in Retail with Quarkus の翻訳記事です。 小売業では、クラウド技術を積極的に導入しています。これは顧客ニーズの変化や季節ごとの需要、競争の激化に対応するためです。アマゾンのようなデジタル小売業者は業界を破壊しています。そして、小売業者はテクノロジーを通じて競争力を維持する方法を模索しています。 小売業者は、クラウドソフトウェアプラットフォームの取得と導入に多額の投資を行っています。そして、Quarkusは Wipro などのシステムインテグレーターが小売業者の顧客のためにクラウドの導入を加速できるよう支援しています。[ 1 ] Quarkus で小売業のイノベーションを推進 Wipro は、世界中のトップ小売業者と協力して俊敏性を獲得することで成功を収めている 小売コンサルティング グループです。Wipro は、デザイン思考、分析、システムインテグレーション、プロダクトエンジニアリング、人工知能、サイバーセキュリティ、ビジネスサポートにおける Wipro の能力を活用し、ショッピングジャーニーを再構築しています。[ 2 ] Wipro Digital チームのソリューションアーキテクトである Arijit Mazumdar 氏は、小売業やその他の業種のコンサルティンググループが顧客のためにクラウド技術を特定し、推進するための支援を行っています。彼らは、デジタルトランスフォーメーションとエンタープライズアプリケーションの近代化を加速させるために協力しています。Arijit は、最近の取り組みの先頭に立っていました。それはQuarkus フレームワークを識別し、評価し、これらの顧客ソリューションの多くに統合するためです。 小売業の技術的課題 "クラウドの上で生まれた"小売業者は、Amazonや他のデジタルスタートアップのように、伝統的な小売業者に迅速な進化を求める圧力をかけています。伝統的な小売業者は、競争力を維持するために競争と差別化のためにテクノロジースタックを進化させ、近代化することを模索しています。 多くの小売業者は伝統的に、標準的なエンタープライズJavaスタック上でミッションクリティカルなアプリケーションを実行してきました。これは重すぎてクラウドネイティブ実装には適していません。これらの小売業者は現在、クラウドネイティブやマイクロサービス・アーキテクチャへの移行を積極的に進めています。そのため、開発者の雇用や再教育を必要とするJavaに代わる言語を模索するようになりました。 小売業者は今、企業のアプリケーションを近代化するために、テクノロジーの転換を猛烈に進めています。受注管理や電子商取引などの従来の既製品によるシステムでは、お客様の拡張性や俊敏性を確保することができません。その結果、これらは拡張性のためマイクロサービスに取って代わられます。それにより、デジタル小売業者との競争に必要な俊敏性が提供されます。 -Arijit Mazumdar 氏、Wipro Digital のソリューションアーキテクト Quarkus に参加 Arijit 氏は、 Red Hat Developers プログラムを通じて Quarkus の存在を知りました。彼はすぐに Quarkus の能力と、自分の組織や顧客に影響を与える可能性に興味を持ちました。彼と彼のチームが Quarkus を調査し、評価する中で、いくつかのことが本当に目立っていました。 Java の専門知識の活用 Wipro の多くの顧客は、Jakarta EE や Spring のような Java フレームワークをエンタープライズ開発に使用しています。Java の限界はクラウドでマイクロサービスアーキテクチャに移行したことで拡大しました。メモリ消費量と起動時間は、より大きなコンテナと VM を必要としていました。彼らの顧客はすでに Golang や Node.js のような Java の代替案を見始めていました。それは従業員を再教育し、新しい言語を学ぶのに時間がかかることを意味していました。 私たちが Quarkus を紹介する前は、多くのお客様がパフォーマンスと効率性を向上させるために、 Go や node.js などの代わりとなるスタックを検討し始めていました。これらの顧客は、新しい言語を選択、新しい開発者を雇ったり、既存のJava開発者を再教育したりしなければならないことに疲れていました。 - Arijit Mazumdar 氏 Quarkus を使用することで、彼らは既存の Java の知識と経験を活用して、求めていた効率性を実現できるようになりました。実際、Wipro チームは、Spring で書かれた既存のアプリケーションを Quarkus に移行するためのパイロットプロジェクトを開始しました。そのリード開発者は Spring の開発者でした。彼は Quarkus のフレームワークを習得して短期間で生産性を上げられました。 Quarkus の学習量の少なさがあった。開発者の一人が Quarkus を使いこなすのに 1 週間、Spring アプリケーションを Quarkus に移行するのに 1 週間かかりました。 - Arijit Mazumdar 氏 開発者の生産性 また、Quarkus は、多くの機能を備えていることも魅力でした。それはJava 開発者がより生産性を高められるようなものです。ライブコーディング、拡張機能のエコシステム、Kubernetes の統合は、開発者の生産性を向上させるために重要な役割を果たしました。 Wipro チームによると、ライブコーディング機能は「ゲームチェンジャー」だったという。ホットリロード機能により、開発者の生産性が大幅に向上し、アプリケーション開発と移行の市場投入までの時間が短縮されました。Wipro の開発者は、Node.jsのような他の言語ではこの機能に慣れていました。しかし、Javaでは慣れていなかったので、これは嬉しい驚きでした。 Quarkus コミュニティは 100 以上の拡張機能 があります。それは、アプリケーションをネイティブの実行ファイルにコンパイルする機能など、フレームワークへの追加機能強化や統合を提供しています。Wipro チームは、RESTEasy、Hibernate ORM、Spring 対応、PostgreSQL など多くの拡張機能を活用しました。Apache Camel の拡張機能は、統合開発のための時間と複雑さを軽減するのに特に役立ちました。Camel の拡張機能により、メインフレームや既製品のアプリケーションのようなレガシーアプリケーションの上に、抽象化や破損防止レイヤを素早く記述できるようになりました。 また、コンテナ化や Kubernetes デプロイメントのための Quarkus のサポートも重要でした。Kubernetes のコンポーネントのほとんどは Dockerfile のように自動生成されます。それは、開発者が Quarkus を使いやすく、より生産性の高いものになっています。 小売店でのユースケース Quarkus がクラウドリソースを効率的に使用できるため、多くのユースケースで理想的なランタイムとなります。Wipro は、Quarkus を単なる新規開発のためのフレームワーク以上のものと捉えています。彼らは既存のアプリケーションの近代化に与える影響を肌で感じているという。前述のプロジェクトの一つに、注文管理アプリケーションの Spring から Quarkus への移行がありました。Quarkus の Spring 互換性拡張機能により、最小限の問題で 1 週間未満でアプリケーションを簡単に移植できました。 Quarkus と Spring API の互換性により、お客様にとって非常に重要な移行時間と複雑さが軽減されました。 - Arijit Mazumdar 氏 Wipro はまた、Java 開発者がイベント駆動型のサーバーレスアプリケーションを作成できるようにするために、Quarkus に大きな機会があると考えています。小売業者は、バッチジョブやリアルタイム処理の一部として多くのタスク処理イベントを利用して注文を受け付け、処理しています。"常に稼働する"サービスは一般的にこれらのタスクに使用されいます。そして、それらは負荷がない場合でもリソースを消費します。例えば、英国の小売顧客は、24 時間稼働している 4 つのサービスを利用しているSaaSプロバイダーから 1 日 3 回の割り当てを受けています。処理をサーバーレスに移行することで、小売業者は割り当て活動があるときに CPU サイクルだけを支払うことで、処理サイクルを大幅に節約しました。 Wipro Digital と Retail のチームは、Quarkus のフレームワークを活用してクラウドコンピューティングの力を顧客に提供し続けることに興奮しています。今後のリリースや機能向上に期待が持てる強力なツールであることが証明されています。 Wipro について Wipro 株式会社は、世界的な情報技術、コンサルティング、ビジネスプロセスサービスのリーディングカンパニーです。私たちは、コグニティブコンピューティング、ハイパーオートメーション、ロボティクス、クラウド、アナリティクス、新技術の力を活用して、お客様がデジタル世界に適応し、成功を収めることができるように支援します。包括的なサービスのポートフォリオ、持続可能性への強いコミットメント、そして良き企業市民として世界的に認められている当社は、18 万人以上の献身的な従業員を擁し、6 大陸のお客様にサービスを提供しています。共にアイデアを発見し、点と点を結びつけることで、より良い、より大胆な新しい未来を築けます。 https://www.wipro.com/content/dam/nexus/en/industries/retail/latest-thinking/digital-transformation-wake-up-call.pdf https://www.wipro.com/en-US/retail/
こんにちは。レッドハットで Chief Technologistとして活動している梅野です。 今日はアプリケーションの中で結構厄介な、「業務のステータス」について書いてみます。 「業務のステータス」とは? 「あの案件の進捗、どうなっている?」とか、上司から聞かれませんか?そんな時、「技術部の高山課長・加藤部長の承認はもらえて、企画部と営業部には承認のお願いに行っていますが、業者から仕様の変更分の再見積もりがまだ来ていなくて、経理部に回せていません!」 「この案件は我社にとって重要な案件だ。関根常務と廣山専務も承認パスに入れておくようにな。来年1月から我社も印鑑レスになるから、プログラムで常務と専務がチェックできるようにしておくように変更要求を出しておいてくれ。ちゃちゃっとな。」 「はい、承知しました... (ぐへぇ、また技術の蒲池さんにお願いするのか... あの人怖いんだよなぁ〜、しかもちゃちゃっとできるわけないっしょ?)」 みたいな話、ありませんか? この話では社内の稟議の例ですが、受付から契約までの流れや仕様公開から入札までの流れなど、「今、業務としてどこまでできているか」の状況をわかるようにしておくのは、業務上重要なことです。コレがわからないと、稟議やら手続きやらを流れに沿って担当者にいちいち確認しに行かなければならなくなります。これが大変なので、皆さんどうしているかというと、DBにフラグカラムを作成し、承認パスの変遷をデータとして書き込み、その組合せでステータスを報告するという、神業的なことをやられております... 業務ステータスの実態  業務を支えるシステムの一つのパーツとして、データベース(DB)があることは言うまでもありません。ですが、私が見てきたお客様の多くは、「フラグ」という名のフィールドをたくさん作っており、その組合せをロジックで判断しており、さらにはステータスを「乱発」されております。業務データ以上の数の「フラグ」カラムがあったんです。しかも、半分くらいは何に使っているかが今の担当者ではわからないという... ステータスをその組合せで作っているし、そのステータスが業務ロジックの中に混在してしまっていました。そうすると、ステータス毎にロジックがコピペ&改変され、ステータスの分岐が複雑性を指数関数的に飛躍させていました。  多くのお客様は、「似たようなロジックがたくさんあるのが悪だ!」とおっしゃいますが、それは単にコピペされたロジック。しかも、微妙にちょっとずつ違うのですが、それは必要なロジックなのです。しかも、コピペしているから実装に時間はかかっていないのです。着眼すべきは、「ステータスの複雑さ」ではないでしょうか。ソースコードのスパゲッティ化の原因にさえ見えてきます。 解決策はあるのか?  簡単な話です。ステータスを専用で管理する仕組み(サービス)にして、ステータスが知りたければ問い合わせをする仕組みにすればよいだけです。業務データとステータス管理を分離させます。ただそれだけです。  「え?いやいや、そんな簡単な話じゃないでしょ?ビジネスプロセスマネージメント(BPM)みたいな製品でやろうとしたって何百パターンも作らないといけないし、差戻し処理とかのときはどうするのよ?業務DBとステータスDBを分けてしまって、片方のCommitが失敗した時はどーすんの?.... 」 等の声が聞こえてきます(妄想の会話ではないところが悲しい...)  昔、話としては流行ったものの導入して成功したという事例をほとんど聞かない、BPM。何故流行らなかったのか、私なりに検証したのが下記です。 1. 承認パターンの複雑化    係長→課長→部長 の順が業務上の正解なのですが、課長が入院してしまった時、先に部長の承認をもらう みたいなパターンが出てくるのは容易に想像できます。こういう場合、係長→部長→課長 の順のプロセスを用意したり、課長の代役で部長が入力したり、DBに無理やりデータを放り込んだり...  等が現実解となっていました。つまり、ツールとして柔軟性に欠けていたのです。 2. 差戻し処理    部門内ならまだしも、部門をまたがるプロセスで差戻しが発生した場合、部門ごとに使っているアプリやDBを「元の状態に戻す」ことが要求されたりしていました。これ、私自身もそういう実装を頼まれたことがあるのですが、「めちゃくちゃ面倒」なのです。絵にすると一直線で、これ以上のシンプルさを求めるのは不可能というレベルのぷろせすであっても、この「差戻し処理」を入れると、あら不思議、実装としては絡み合った朝顔のつるのような物が最初から出来上がります... 3. システム的なデータの流れを記述    タスクの連携をお絵かきソフト的な感じで書けるものですから、承認ボタンを押されたあとの後続処理を、トランザクション管理をしながら他システム連携させてしまう使い方をしているケースが結構ありました。上記の差戻し処理もそうですが、ダメだった場合のrollbackが超絶面倒なのです。面倒なくらいならやればよいのですが、他のシステムが格納したデータを「上書き」してしまい、元に戻せない状況まで発生するわけです。 (実際には、その時のエラーハンドリングまでやる必要があります... 吐きそうだった...) に関しては、今は「Case Management」という考え方、モジュールが提供されています。この場合、とにかく係長・課長・部長の3人の承認が下りればよく、その順序性は問わないのです。だとしたら、「順序は問わずに3つの承認が揃ったら次に進む」ということにすればよいのです。実際には、係長の承認のあと、XXシステムにデータが登録されたことを持って課長が承認を行う みたいなことがあります。その場合も、システムへのデータ登録というイベントを掴むことを開始条件とすることで、課長の承認タスクを開始させるということができるようになっています。ここは単にイベントの組合せを書くだけではなく、ルールエンジンなどでより高度な状況の判断を行うこともできます。 については、諦めてください。笑。 というか、「差戻し」ってその条件では承認できませんよと「却下」されたのと同じなんです。だとしたら、その申請プロセスとしては「却下」として終了させ、もう一度申請を始めるべきなんです。「いやいや、とはゆうても膨大な入力、もう一度やりたくないよ、価格を5%値引けば通るなら、そこだけ変えてよ!」という話もよくわかります。であれば、あるスナップショットまでを「自動的に入力」ということにして、新たなプロセスとして進行させるとしてしまえばよいのです。元には戻さず、前に向かうだけ。このポリシーにするだけでも、かなりスッキリするはずです。 は、業務的な流れをBPMで書くべきであり、システム的な流れはBPMではなく、システム連携ツールで行うべきです。極論でいうと、BPMが管理すべきものは「人の承認の流れ」もしくは「機械査定」のように機械で判定した履歴を残したいケースだけです。システム的な連携(業務DBへの書き込みとか他システムへのデータの送信)などは、BPMを呼び出すアプリ側でやるべき話です。ただ、業務データとステータスの管理テーブルを、同じスキーマで作成して同時にコミットさせる というのはアリだと思います。それは業務データテーブルにステータス管理項目を入れるのではなく、業務データとステータスの管理テーブルを異なるスキーマにしておき、一括コミットさせることでデータの泣別れはかなりの確率で防げます。 Red Hat Process Automation Managerという製品  レッドハットでは、Red Hat Process Automation Manager (RHPAM)という製品を提供しています。これが「案件の進捗管理」にかなり有効です。RHPAMは、プロセスサービスとして、単一のサービス提供型アプリケーションとなります。アプリケーションロジックからデータとプロセスを分離させることで、アプリケーションの簡素化、Case Managementのような非定型なプロセスの作成・管理・実行、DBの軽量化などのメリットが出てきます。それぞれのタスクでどれだけの時間がかかったのか、担当者ごと・タスクごと等にわけてレポートも出ますので、従来のBPMが標榜していたような業務プロセス改善のためのツールにももちろん適用できます。  コロナ禍において、ペーパーレス・印鑑レスに国全体・世界全体が向かっています。従来型のアプリケーションの改修ではなく、サービス提供型のアプリケーション・アーキテクチャを採用し、業務要件への柔軟性を持って対応できるようなアプリケーションにチェンジしてみてはいかがでしょうか。製品単体だけでなく、どのようにしてうまく使えばよいかのノウハウも、レッドハットは提供していますよ!
レッドハットの森若です。 RHEL 8 では、 tlog という端末の入出力を記録する仕組みが導入されています。今回はこのtlogを紹介します。 シーン1 トラブルシュート ショートコント「チャットにて」 A> foobar.logっていうファイルがどこかにあるはずなんだけどどうやってみつけたらいい? B> "$ locate foobar.log" ってやったらいいよ A> command not foundってでた B> じゃあ"$ find / -name foobar.log" で出る? A> またcommand not foundってでた B> さすがにそれはないでしょー? A> でも bash: $: command not found ってでてる。 B> もしかして $ をコマンドとして入力してる? ここまで極端でなくても、作業の厳密な記録や、試行錯誤したときに「何を入力して何が出力されたか」をはっきり人に伝えるのはなかなか難しいものです。 この問題に対して端末の入出力を記録するソフトウェアが利用されます。その一種が今回紹介するtlogです。 インストールはRHEL 8にて、tlogパッケージを導入します。 # yum install tlog その後記録をはじめる時に、以下のように-o オプションでログファイルを指定して tlog-rec コマンドを実行します。 $ tlog-rec -o mysession.log tlog-recの子プロセスとしてシェルが起動しますので、そのあとは普通に作業をおこない、終わったらシェルを終了します。シェルの実行が終わるとtlog-recも実行を終了し、ログファイルの中には記録された出力情報がJSON形式で記録されます。 mysession.logの中身は以下のようになっていて、おおよそ10秒毎にバッファリングして記録されます。 {"ver":"2.2","host":"rhel82","rec":"6cca1ac609954a8c9b2b5f2350c74c2c-11aa-1e1ef","user":"kmoriwak","term":"xterm-256color","session":5,"id":1,"pos":0,"timing":"=80x24+90>43+1275>1+77>1+90>2+1>534+1>43+2788>1+54>1+72>1+38>1+112>1+55>1+67>1+55>1+268>1+706>1+77>1+76>1+73>1+134>1+89>1+71>1+67>1+435>17+291>5+71>5+150>5+128>5+390>51+291>1+255>1+386>1+285>1+106>1+299>1+250>1+211>1","in_txt":"","in_bin":[],"out_txt":"\u001b]0;kmoriwak@rhel82:~\u0007[kmoriwak@rhel82 ~]$ ls\r\n3903028196380168456-key.pem \u001b[0m\u001b[38;5;40mkubectl (==中略==) [C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C > huga.","out_bin":[]} このJSONファイルは"timing" という項目で画面出力のタイミングを保持していますので、 tlog-playコマンドに処理させることで、表示の待ち時間タイミングも含めて再現できます。(早送りやジャンプの機能もあります) $ tlog-play -i mysession.log このファイルを送ると「何がいつ端末に表示されたか」がほとんど完全に再現されるわけです(入力はパスワードなども含むため、デフォルトでは記録しませんが、オプション指定により記録することもできます)。 tlog-playコマンドの他、Web Consoleと統合されたセッション記録のプレーヤーもあります。 Web Console内でのセッション記録再生 シーン2 監査のためのセッション記録 ログイン時に、シェルのかわりに tlog-rec-session を起動することで、tlog-recと同じ仕組みでログインセッション全体を記録することができます。こちらはの利用シーンは、管理者およびユーザによる操作の監査ログとして利用したい場合に、全ての作業をログに残すため使います。 セッション記録は以下の図のような仕組みでおこない、ユーザの諸情報を管理するSSSDが設定に従い、記録対象のアカウントについてはtlog-rec-sessionをシェルとして実行し、かつ環境変数 SHELLは本来指定されていたシェルになるよう調整します。 tlog + SSSDによるセッション記録概要 典型的にはSSSDを利用したログインをおこない、セッション記録をおこないます。 こちらの設定方法については以下のドキュメントをごらんください。 access.redhat.com 注意点 いくつかtlog利用時の注意点を書いていきます。 tlog-playで記録を再生するとき、端末のサイズが異なると表示が崩れます。timing内の =80x24 のような部分で端末のサイズを記録していますので崩れた場合は記録時の端末サイズとずれていないか確認しましょう。cockpitで表示する場合にはこの情報から自動的にブラウザ上の再生領域をリサイズしてくれます。 rootユーザが直接ログインできる設定や、SSSDを利用しないシステムの場合、/etc/passwd エントリを使うことが多いはずです。この場合cockpitからの設定ではrootでログインしたセッションを記録できません。上のドキュメント「2.5. SSSD を使用せずに録画するユーザーまたはユーザーグループの設定」を参考に、ログインシェルを /usr/bin/tlog-rec-session と指定することで利用できます。 セッション記録をrsyslogに保存する場合、MaxMessageSizeを3KB以上に設定します。デフォルトだと2KBで、記録が再現できなくなる場合があります。 セッション記録をjournalに保存する場合、デフォルトでは再起動すると消えてしまいます。 # mkdir /var/log/journal のようにしてjournalを永続化します。 GUIセッションは記録されません。監査ログに利用したい場合、GUIセッションでのログインや操作は記録できません。 参考資料 Upstreamのドキュメント github.com RHEL 8 のドキュメント access.redhat.com 端末のセッション記録をためせるハンズオンラボ https://lab.redhat.com/session-recording-tlog-jp 過去に私が書いたtlog紹介資料 端末のセッション記録 - Speaker Deck
この記事は Rookと仲間たち、クラウドネイティブなストレージの Advent Calendar 2020 4日目の記事です。 お久しぶりです。レッドハットでストレージを中心にクラウドインフラを生業にしている宇都宮です。 去年のアドベントカレンダーぶりかもしれませんね、今年もがんばってやってますので、ストレージ愛が五臓六腑に沁み渡るみなさんのブログを楽しんで下さいね!今日はRookのブログから閑話休題で、CephのMultiSiteについて書いていきます。 qiita.com あとRookのTwitterアカウント、 @japan_rook のフォローお願いしまーす! サイト障害に耐えるためのサイト間レプリケーション 一般的にオブジェクトストレージサービスはサイト障害に耐えられるよう、バックグラウンドでサイト間レプリケーション等が行われていることが多いと思います。 正直オブジェクトストレージはブロックやファイルと違って、高いパフォーマンスや強い整合性が期待されない (誤解を恐れず言うと、期待してはいけない) ストレージサービスなので、同期のオーバーヘッドを気にすることなくレプリケーションできます。 KubernetesやOpenStack、Proxmox等のプラットフォームのバックエンドストレージとして使われることの多いCephですが、単体ではオブジェクトストレージとして使われているケースが多いです。 Cephでサイト障害に耐えるためのパターンは2つに大別されます。 Stretched Cluster 複数サイトで動くMON/OSD/RGW等のコンポーネントで、1つのCephクラスターを構成する クラスター間レプリケーション/ミラー 各サイトで動く複数のCephクラスター間で、データのレプリケーション/ミラーを構成する 一つ目のStretched Clusterは、運用対象が1つのクラスターなのでシンプルです。 writeの整合性はRADOSが担保するので各サイトActiveで使えるし、RPOも障害直前、RTOも限りなく0でしょう。 ただし、サイト間ネットワークの安定性が命になります。例えばサイト間ネットワークが途切れると、サイトを跨いでreplicated poolを組んでいると全サイトでOSDへの同期が完了できないためwriteが遅くなったり、MON同士の通信ができなくなってクラスター全体の構成が不安定になったりします。 どのサイトも普通に生きているのに、サービスに悪影響を及ぼすリスクがあるというわけです。 うまくCRUSH treeの設計を行うと回避できるかもしれませんが、そうすると構成は複雑になるので運用側が大変になります。 そういった観点からStretched Clusterは実践的には難しく、比較的近距離のサイト間でなら成立する可能性はある、というレベルと考えます。 HW/SDSを問わず、ストレージでサイト障害に対応する方法の多くは、二点目のようなクラスター間でのレプリケーションでしょう。 もちろんこれはこれで考慮点はあります。RPO、RTOはStretched Clusterより長くなるし、Active-ActiveとするかActive-Passiveとするかで切り替え/切り戻しの際にデータを整合性をどう担保するか、などでしょうか。 とは言え、サイト間ネットワークが途切れても、各サイトのクラスターは普通に動くのでサービスへの影響がStretched Clusterよりは俄然低いのは大きなメリットです。 もちろんCephでもクラスター間レプリケーションは可能です。ブロックストレージの場合は "RBD Mirror" と呼ばれる機能で、オブジェクトストレージの場合は、今回のトピックの "MultiSite" と呼ばれる機能です。 Ceph NanoでMultiSiteをやってみよう Ceph MultiSiteはRGW(Rados Gateway)の機能です。複数のクラスターにあるRGW間でBucketなどを同期することができます。 どうなるものかお見せしたいのですが、Cephのクラスターを立てるのは割と大変です。ですので、今回はCeph Nanoを使ってお見せします。 Ceph Nanoについては 去年書いたブログ を見て下さい。 Ceph Nanoで2つのCephクラスターを立てて、その間でレプリケーションをするようにしてみます。 同じマシンの上にクラスターを作ってもよいのですが、下図のようなイメージで2つの違うマシンの上でそれぞれ作ってみます。 [root@master ~]$ ./cn cluster start cn1 -f huge 2020/12/03 12:41:16 Running cluster cn1 | image ceph/daemon | flavor huge {4GB Memory, 2 CPU} ... Endpoint: http://10.208.81.35:8000 Dashboard: http://10.208.81.35:5000 Access key: DFE06L7ZSW0CBRHYTIMJ Secret key: BNAi3vAhzyGb0rmnNrJkItQWhqADuydoUELLp7jt Working directory: /usr/share/ceph-nano [root@secondary ~]$ ./cn cluster start cn2 -f huge 2020/12/03 12:41:36 Running cluster cn2 | image ceph/daemon | flavor huge {4GB Memory, 2 CPU} ... Endpoint: http://10.208.81.18:8000 Dashboard: http://10.208.81.18:5000 Access key: JRLYVCV1XMS0YDXK7AXH Secret key: ta0ikPv6CKj5qOfAyw23MH1aFpsn8AVZRGMQkjNQ Working directory: /usr/share/ceph-nano Endpointとして8000番ポートが指定されています。 またAccess keyとSecret keyが表示されています。Ceph Nanoは立ち上げると自動的に"nano"というRGWユーザーを作りますが、表示されているのはこのユーザーのものです。 今回は"nano"ユーザーは使わないので、このkeyは無視してもらって大丈夫です。 とりあえずクラスターが2つできました。 Masterでzone, zonegroup, realmを設定 MultiSiteをする際にはzone, zonegroup, realmを設定する必要があります。 zoneはレプリケーションをする最小の単位で、クラスターに存在するRGWはどれか1つのzoneに所属します。zoneは1つのクラスターで作成され、zone内のRGWが管理するbucketはレプリケーションをする対象となります。 zonegroupは名前の通り複数のzoneを束ねたもので、zoneは1つのzonegroupに所属します。zonegroupはクラスターをまたいで組むことができ、クラスター間でzoneの情報を共有します。zonegroup内に存在するzoneの間で、bucketはレプリケーションされます。 realmはzonegroupを束ねるユニークなnamespaceです。 クラスターが複数ありそれぞれレプリケーションする先が異なったり、bucketごとにActive-ActiveとActive-Passiveを使い分けたり、比較的複雑なレプリケーション構成をとりたい場合は、zonegroupやrealmを複数作って制御することができます。 今回は下図のように最もシンプルなパターンで、2 zones -> 1 zonegroup -> 1 realm の関係でいきます。 それではMaster側のクラスターでzone, zonegroup, realmを設定します。包含関係から作成するのはrealmからです。 Ceph Nanoクラスターに入るには、 cn cluster enter で入ることができます。 [root@master cephnano]# ./cn cluster enter cn1 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin realm create --rgw-realm=rlm --default { "id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "name": "rlm", "current_period": "332fc423-02fe-427e-85b9-97ffe24f9197", "epoch": 1 } [root@ceph-nano-cn1-faa32aebf00b /]# [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin zonegroup create --rgw-zonegroup=zg --endpoints=http://10.208.81.35:8000 --rgw-realm=rlm --master --default { "id": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "name": "zg", "api_name": "zg", "is_master": "true", "endpoints": [ "http://10.208.81.35:8000" ], "hostnames": [], "hostnames_s3website": [], "master_zone": "", "zones": [], "placement_targets": [], "default_placement": "", "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "sync_policy": { "groups": [] } } [root@ceph-nano-cn1-faa32aebf00b /]# [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin zone create --rgw-zonegroup=zg --rgw-zone=z1 --endpoints=http://10.208.81.35:8000 --default { "id": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "name": "z1", "domain_root": "z1.rgw.meta:root", "control_pool": "z1.rgw.control", "gc_pool": "z1.rgw.log:gc", "lc_pool": "z1.rgw.log:lc", "log_pool": "z1.rgw.log", "intent_log_pool": "z1.rgw.log:intent", "usage_log_pool": "z1.rgw.log:usage", "roles_pool": "z1.rgw.meta:roles", "reshard_pool": "z1.rgw.log:reshard", "user_keys_pool": "z1.rgw.meta:users.keys", "user_email_pool": "z1.rgw.meta:users.email", "user_swift_pool": "z1.rgw.meta:users.swift", "user_uid_pool": "z1.rgw.meta:users.uid", "otp_pool": "z1.rgw.otp", "system_key": { "access_key": "", "secret_key": "" }, "placement_pools": [ { "key": "default-placement", "val": { "index_pool": "z1.rgw.buckets.index", "storage_classes": { "STANDARD": { "data_pool": "z1.rgw.buckets.data" } }, "data_extra_pool": "z1.rgw.buckets.non-ec", "index_type": 0 } } ], "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3" } はい、できました。 zonegroup create と zone create で --endpoint のオプションがありますが、ここにRGWのエンドポイントを指定します。 また、Poolについては特段何も指定していませんが、RGWデフォルトのpoolを使っています。実際に使う場合は新規にpoolを切ると思うので、その場合は radosgw-admin zone placement を使って指定します。 レプリケーション用のsystem userを作成 クラスターをまたいでRGW間でデータやrealm等の構成を共有するために、両者で共通のシステムユーザーが必要となります。 これはMaster側で作って、後でSecondaryからpullすることで共有されます。 このシステムユーザーの名前は何でもよいのですが、作られるAccess keyとSecret keyは重要なのでメモしておきましょう。 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin user create --uid="syncuser" --display-name="sync user" --system { "user_id": "syncuser", "display_name": "sync user", "email": "", "suspended": 0, "max_buckets": 1000, "subusers": [], "keys": [ { "user": "syncuser", "access_key": "57ZYN8XHW9V03VYGEG9P", "secret_key": "BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS" } ], "swift_keys": [], "caps": [], "op_mask": "read, write, delete", "system": "true", "default_placement": "", "default_storage_class": "", "placement_tags": [], "bucket_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "user_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "temp_url_keys": [], "type": "rgw", "mfa_ids": [] } この syncuser がMaster側のzoneを操作できるよう、先程作成したzoneにAccess keyとSecret keyの情報を追加します。 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin zone modify --rgw-zone=z1 --access-key=57ZYN8XHW9V03VYGEG9P --secret=BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS { "id": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "name": "z1", "domain_root": "z1.rgw.meta:root", "control_pool": "z1.rgw.control", "gc_pool": "z1.rgw.log:gc", "lc_pool": "z1.rgw.log:lc", "log_pool": "z1.rgw.log", "intent_log_pool": "z1.rgw.log:intent", "usage_log_pool": "z1.rgw.log:usage", "roles_pool": "z1.rgw.meta:roles", "reshard_pool": "z1.rgw.log:reshard", "user_keys_pool": "z1.rgw.meta:users.keys", "user_email_pool": "z1.rgw.meta:users.email", "user_swift_pool": "z1.rgw.meta:users.swift", "user_uid_pool": "z1.rgw.meta:users.uid", "otp_pool": "z1.rgw.otp", "system_key": { "access_key": "57ZYN8XHW9V03VYGEG9P", "secret_key": "BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS" }, "placement_pools": [ { "key": "default-placement", "val": { "index_pool": "z1.rgw.buckets.index", "storage_classes": { "STANDARD": { "data_pool": "z1.rgw.buckets.data" } }, "data_extra_pool": "z1.rgw.buckets.non-ec", "index_type": 0 } } ], "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3" } ここまでできたら概ねMaster側の作業は終わりです。最後にzoneやzonegroup等の構成変更をcommitするべく radosgw-admin period update --commit をします。periodはrealmが持つ構成変更ログのようなものです。 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin period update --commit { "id": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "epoch": 1, "predecessor_uuid": "332fc423-02fe-427e-85b9-97ffe24f9197", "sync_status": [], "period_map": { "id": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "zonegroups": [ { "id": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "name": "zg", "api_name": "zg", "is_master": "true", "endpoints": [ "http://10.208.81.35:8000" ], "hostnames": [], "hostnames_s3website": [], "master_zone": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "zones": [ { "id": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "name": "z1", "endpoints": [ "http://10.208.81.35:8000" ], "log_meta": "false", "log_data": "false", "bucket_index_max_shards": 11, "read_only": "false", "tier_type": "", "sync_from_all": "true", "sync_from": [], "redirect_zone": "" } ], "placement_targets": [ { "name": "default-placement", "tags": [], "storage_classes": [ "STANDARD" ] } ], "default_placement": "default-placement", "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "sync_policy": { "groups": [] } } ], "short_zone_ids": [ { "key": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "val": 2054423084 } ] }, "master_zonegroup": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "master_zone": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "period_config": { "bucket_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "user_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 } }, "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "realm_name": "rlm", "realm_epoch": 2 } RGWを zone:z1 に所属させることをceph.confの [client.rgw] セクションに追記して、RGWを再起動します。Ceph Nanoの場合は cn cluster restart でクラスター再起動をします。 [root@ceph-nano-cn1-faa32aebf00b /]# vi /etc/ceph/ceph.conf [root@ceph-nano-cn1-faa32aebf00b /]# grep -A10 "client.rgw.ceph-nano-cn1" /etc/ceph/ceph.conf [client.rgw.ceph-nano-cn1-faa32aebf00b] rgw dns name = ceph-nano-cn1-faa32aebf00b rgw enable usage log = true rgw usage log tick interval = 1 rgw usage log flush threshold = 1 rgw usage max shards = 32 rgw usage max user shards = 1 log file = /var/log/ceph/client.rgw.ceph-nano-cn1-faa32aebf00b.log rgw frontends = beast endpoint=0.0.0.0:8000 rgw zone = z1 ←追記 [root@ceph-nano-cn1-faa32aebf00b /]# exit exit [root@master cephnano]# ./cn cluster restart cn1 2020/12/03 14:40:37 Restarting cluster cn1... Secondaryでzone, zonegroup, realmの設定 次にSecondary側でzone, zonegroup, realmを設定します。realmとzonegroupはMasterからpullするだけなので簡単です。pullする時には、Master RGWのendpointと syncuser のAccess keyとSecret keyを使います。 [root@secondary cephnano]# ./cn cluster enter cn2 [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin realm pull --url=http://10.208.81.35:8000 --access-key=57ZYN8XHW9V03VYGEG9P --secret=BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS { "id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "name": "rlm", "current_period": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "epoch": 2 } [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin period pull --url=http://10.208.81.35:8000 --access-key=57ZYN8XHW9V03VYGEG9P --secret=BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS { "id": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "epoch": 2, "predecessor_uuid": "332fc423-02fe-427e-85b9-97ffe24f9197", "sync_status": [], "period_map": { "id": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "zonegroups": [ { "id": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "name": "zg", "api_name": "zg", "is_master": "true", "endpoints": [ "http://10.208.81.35:8000" ], "hostnames": [], "hostnames_s3website": [], "master_zone": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "zones": [ { "id": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "name": "z1", "endpoints": [ "http://10.208.81.35:8000" ], "log_meta": "false", "log_data": "false", "bucket_index_max_shards": 11, "read_only": "false", "tier_type": "", "sync_from_all": "true", "sync_from": [], "redirect_zone": "" } ], "placement_targets": [ { "name": "default-placement", "tags": [], "storage_classes": [ "STANDARD" ] } ], "default_placement": "default-placement", "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "sync_policy": { "groups": [] } } ], "short_zone_ids": [ { "key": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "val": 2054423084 } ] }, "master_zonegroup": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "master_zone": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "period_config": { "bucket_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "user_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 } }, "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "realm_name": "rlm", "realm_epoch": 2 } [root@ceph-nano-cn2-faa32aebf00b /]# [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin realm list { "default_info": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "realms": [ "rlm" ] } [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin zonegroup list { "default_info": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "zonegroups": [ "zg", "default" ] } radosgw-admin realm list と radosgw-admin zonegroup list の結果から、Masterから正しくrealmとzonegroupの情報をpullできていることが分かるはずです。 それではzoneを作成します。Masterと同じように作成しますが、Secondary RGWのエンドポイントを指定し、Access keyとSecret keyは syncuser のものを指定します。 [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin zone create --rgw-zonegroup=zg --rgw-zone=z2 --endpoints=http://10.208.81.18:8000 --access-key=57ZYN8XHW9V03VYGEG9P --secret=BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS 2020-12-03T05:50:37.846+0000 7fb33d5c81c0 0 failed reading obj info from .rgw.root:zone_info.9b505afe-3229-4b80-8a69-ffbaea14ec25: (2) No such file or directory 2020-12-03T05:50:37.846+0000 7fb33d5c81c0 0 WARNING: could not read zone params for zone id=9b505afe-3229-4b80-8a69-ffbaea14ec25 name=z1 { "id": "ac746b19-c165-453e-abed-3e528c13377a", "name": "z2", "domain_root": "z2.rgw.meta:root", "control_pool": "z2.rgw.control", "gc_pool": "z2.rgw.log:gc", "lc_pool": "z2.rgw.log:lc", "log_pool": "z2.rgw.log", "intent_log_pool": "z2.rgw.log:intent", "usage_log_pool": "z2.rgw.log:usage", "roles_pool": "z2.rgw.meta:roles", "reshard_pool": "z2.rgw.log:reshard", "user_keys_pool": "z2.rgw.meta:users.keys", "user_email_pool": "z2.rgw.meta:users.email", "user_swift_pool": "z2.rgw.meta:users.swift", "user_uid_pool": "z2.rgw.meta:users.uid", "otp_pool": "z2.rgw.otp", "system_key": { "access_key": "57ZYN8XHW9V03VYGEG9P", "secret_key": "BhLuCDHkFRtdbJTvNJCVP7Powzu7aThdm7KDX9vS" }, "placement_pools": [ { "key": "default-placement", "val": { "index_pool": "z2.rgw.buckets.index", "storage_classes": { "STANDARD": { "data_pool": "z2.rgw.buckets.data" } }, "data_extra_pool": "z2.rgw.buckets.non-ec", "index_type": 0 } } ], "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3" } zone構成が変わったのでperiodのupdateを行い、最後にMasterと同じように、 zone:z2 の情報をceph.confに追記して、restartします。 [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin period update --commit 2020-12-03T05:53:16.914+0000 7f961cc901c0 1 Cannot find zone id=ac746b19-c165-453e-abed-3e528c13377a (name=z2), switching to local zonegroup configuration Sending period to new master zone 9b505afe-3229-4b80-8a69-ffbaea14ec25 { "id": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "epoch": 3, "predecessor_uuid": "332fc423-02fe-427e-85b9-97ffe24f9197", "sync_status": [], "period_map": { "id": "6f70ae90-de8a-47c3-8e77-2b58532728d5", "zonegroups": [ { "id": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "name": "zg", "api_name": "zg", "is_master": "true", "endpoints": [ "http://10.208.81.35:8000" ], "hostnames": [], "hostnames_s3website": [], "master_zone": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "zones": [ { "id": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "name": "z1", "endpoints": [ "http://10.208.81.35:8000" ], "log_meta": "false", "log_data": "true", "bucket_index_max_shards": 11, "read_only": "false", "tier_type": "", "sync_from_all": "true", "sync_from": [], "redirect_zone": "" }, { "id": "ac746b19-c165-453e-abed-3e528c13377a", "name": "z2", "endpoints": [ "http://10.208.81.18:8000" ], "log_meta": "false", "log_data": "true", "bucket_index_max_shards": 11, "read_only": "false", "tier_type": "", "sync_from_all": "true", "sync_from": [], "redirect_zone": "" } ], "placement_targets": [ { "name": "default-placement", "tags": [], "storage_classes": [ "STANDARD" ] } ], "default_placement": "default-placement", "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "sync_policy": { "groups": [] } } ], "short_zone_ids": [ { "key": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "val": 2054423084 }, { "key": "ac746b19-c165-453e-abed-3e528c13377a", "val": 1074715361 } ] }, "master_zonegroup": "e2a4ab0d-a871-4aaa-af1e-7be3cd16615e", "master_zone": "9b505afe-3229-4b80-8a69-ffbaea14ec25", "period_config": { "bucket_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "user_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 } }, "realm_id": "e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3", "realm_name": "rlm", "realm_epoch": 2 } [root@ceph-nano-cn2-faa32aebf00b /]# [root@ceph-nano-cn2-faa32aebf00b /]# vi /etc/ceph/ceph.conf [root@ceph-nano-cn2-faa32aebf00b /]# grep -A10 "client.rgw.ceph-nano-cn2" /etc/ceph/ceph.conf [client.rgw.ceph-nano-cn2-faa32aebf00b] rgw dns name = ceph-nano-cn2-faa32aebf00b rgw enable usage log = true rgw usage log tick interval = 1 rgw usage log flush threshold = 1 rgw usage max shards = 32 rgw usage max user shards = 1 log file = /var/log/ceph/client.rgw.ceph-nano-cn2-faa32aebf00b.log rgw frontends = beast endpoint=0.0.0.0:8000 rgw zone = z2 [root@ceph-nano-cn2-faa32aebf00b /]# exit exit [root@secondary cephnano]# ./cn cluster restart cn2 2020/12/03 14:58:44 Restarting cluster cn2... はい、お疲れさまでした。これでzone間のレプリケーションの設定ができました。MasterとSecondaryの両方に入って、 radosgw-admin sync status を実行してみると同期状況が確認できます。 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin sync status realm e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3 (rlm) zonegroup e2a4ab0d-a871-4aaa-af1e-7be3cd16615e (zg) zone 9b505afe-3229-4b80-8a69-ffbaea14ec25 (z1) metadata sync no sync (zone is master) data sync source: ac746b19-c165-453e-abed-3e528c13377a (z2) syncing full sync: 0/128 shards incremental sync: 128/128 shards data is caught up with source [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin sync status realm e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3 (rlm) zonegroup e2a4ab0d-a871-4aaa-af1e-7be3cd16615e (zg) zone ac746b19-c165-453e-abed-3e528c13377a (z2) metadata sync syncing full sync: 0/64 shards incremental sync: 64/64 shards metadata is caught up with master data sync source: 9b505afe-3229-4b80-8a69-ffbaea14ec25 (z1) syncing full sync: 0/128 shards incremental sync: 128/128 shards data is caught up with source この出力を見ると、それぞれ、 data sync source がお互いのzoneを指定しています。 つまりこれは、 z1 側で保存されたオブジェクトは z2 へレプリケーションされ、 z2 側で保存されたオブジェクトは z1 へレプリケーションされる、Active-Activeなレプリケーションを意味します。 S3 clientからオブジェクトを置いてみよう それでは本当にレプリケーションが稼働するのか、クライアントからオブジェクトを保存してみます。 S3 client用のユーザーを作成する Master側に、先程 syncuser を作ったのと同じように、 testuser というユーザーを作成します。今度はsystem userではないので、 --system オプションはつけません。 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin user create --uid="testuser" --display-name="test user" { "user_id": "testuser", "display_name": "test user", "email": "", "suspended": 0, "max_buckets": 1000, "subusers": [], "keys": [ { "user": "testuser", "access_key": "WMJLX79PAZ3M24ZYACX1", "secret_key": "u4ePP8FxhmnHfs83TDQFSEWbC5VoflrnMe3JqExS" } ], "swift_keys": [], "caps": [], "op_mask": "read, write, delete", "default_placement": "", "default_storage_class": "", "placement_tags": [], "bucket_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "user_quota": { "enabled": false, "check_on_raw": false, "max_size": -1, "max_size_kb": 0, "max_objects": -1 }, "temp_url_keys": [], "type": "rgw", "mfa_ids": [] } [root@ceph-nano-cn1-faa32aebf00b /]# [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin user list [ "syncuser", "testuser" ] さて、 testuser が作られましたが、Secondaryの方でも radosgw-admin user list を実行してみましょう。こちらにも testuser が同期されているはずです。 [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin user list [ "syncuser", "testuser" ] testuserのkeyを使ってS3 clientでオブジェクトを置く おまたせしました、それでは testuser のkeyを使ってbucketを作り、オブジェクトを置いてみます。 S3 clientはなんでもいいのですが、awscliを使ってローカルのファイルを s3 cp します。 まずはMaster側のRGW(z1)のendpointを指定してbucketを作ります。 [root@s3c ~]# aws configure AWS Access Key ID []: WMJLX79PAZ3M24ZYACX1 AWS Secret Access Key []: u4ePP8FxhmnHfs83TDQFSEWbC5VoflrnMe3JqExS Default region name [None]: Default output format [None]: [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 mb s3://z1-bucket make_bucket: z1-bucket [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 ls 2020-12-03 15:45:23 z1-bucket MasterとSecondaryの両方でbucketが確認できると思います。これはMaster側で作られたbucketがすぐにSecondaryに同期されているためです。 [root@ceph-nano-cn1-faa32aebf00b /]# radosgw-admin bucket list [ "z1-bucket" ] [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin bucket list [ "z1-bucket" ] それでは何かしらMaster側にファイルを置いてみましょう。丁度いい具合にRHEL8のISOイメージがあるのでこれを置いてみます。 [root@s3c ~]# ll /mnt/share/rhel-8.2-x86_64-dvd.iso -rw-r--r--. 1 root root 8436842496 8月 12 12:36 /mnt/share/rhel-8.2-x86_64-dvd.iso [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 cp /mnt/share/rhel-8.2-x86_64-dvd.iso s3://z1-bucket/rhel8img upload: ../mnt/share/rhel-8.2-x86_64-dvd.iso to s3://z1-bucket/rhel8img [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 ls s3://z1-bucket 2020-12-03 15:56:44 8436842496 rhel8img [root@s3c ~]# [root@s3c ~]# aws --endpoint-url=http://10.208.81.18:8000 s3 ls s3://z1-bucket [root@s3c ~]# ...(転送終了後) [root@s3c ~]# aws --endpoint-url=http://10.208.81.18:8000 s3 ls s3://z1-bucket 2020-12-03 15:56:44 8436842496 rhel8img s3 cp が完了すると、すぐにMasterからSecondaryへの転送が始まります。 転送中はSecondaryに対して s3 ls を実行してもオブジェクトは出てきません。 ブロックストレージのレプリケーションやファイルストレージのコピーとは違い、転送元のストレージに書かれたデータをブロック単位で次々に転送することはありません。転送元にオブジェクトを書き切ってから、転送先にレプリケーションを行います。 転送中のSecondaryマシンでiftopの出力が下の図です。1Gbpsで繋がっているのでMaster(.35)からSecondary(.18)へワイヤースピードに近い速度で転送しています。 転送中は、 radosgw-admin sync status の出力で、 xx shards are recovering ; recovering shareds: [XX] と表示されます。完全に同期したら data is caught up with source と表示されます。 [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin sync status realm e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3 (rlm) zonegroup e2a4ab0d-a871-4aaa-af1e-7be3cd16615e (zg) zone ac746b19-c165-453e-abed-3e528c13377a (z2) metadata sync syncing full sync: 0/64 shards incremental sync: 64/64 shards metadata is caught up with master data sync source: 9b505afe-3229-4b80-8a69-ffbaea14ec25 (z1) syncing full sync: 0/128 shards incremental sync: 128/128 shards 1 shards are recovering recovering shards: [76] ... (同期完了後) ... [root@ceph-nano-cn2-faa32aebf00b /]# radosgw-admin sync status realm e1bd3bc0-9ef8-460a-8d24-cd69ba7e62e3 (rlm) zonegroup e2a4ab0d-a871-4aaa-af1e-7be3cd16615e (zg) zone ac746b19-c165-453e-abed-3e528c13377a (z2) metadata sync syncing full sync: 0/64 shards incremental sync: 64/64 shards metadata is caught up with master data sync source: 9b505afe-3229-4b80-8a69-ffbaea14ec25 (z1) syncing full sync: 0/128 shards incremental sync: 128/128 shards data is caught up with source これでMaster->Secondaryのレプリケーションはうまくいっていることが分かりました。 それでは反対にSecondary->Masterのレプリケーションを試してみましょう。先程と同様にS3 clientからSeconaryにbucketを作成し、ファイルを置いてみます。 [root@s3c ~]# aws --endpoint-url=http://10.208.81.18:8000 s3 mb s3://z2-bucket make_bucket: z2-bucket [root@s3c ~]# aws --endpoint-url=http://10.208.81.18:8000 s3 ls 2020-12-03 15:45:23 z1-bucket 2020-12-03 16:07:00 z2-bucket [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 ls 2020-12-03 15:45:23 z1-bucket 2020-12-03 16:07:00 z2-bucket [root@s3c ~]# aws --endpoint-url=http://10.208.81.18:8000 s3 cp /mnt/share/rhel-8.2-x86_64-dvd.iso s3://z2-bucket/rhel8img_second upload: ../mnt/share/rhel-8.2-x86_64-dvd.iso to s3://z2-bucket/rhel8img_second [root@s3c ~]# aws --endpoint-url=http://10.208.81.18:8000 s3 ls s3://z2-bucket 2020-12-03 16:21:37 8436842496 rhel8img_second [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 ls s3://z2-bucket ...(転送終了後) [root@s3c ~]# aws --endpoint-url=http://10.208.81.35:8000 s3 ls s3://z2-bucket 2020-12-03 16:21:37 8436842496 rhel8img_second Master->Secondaryと同じような感じですね。iftopの出力は先程とは反対に、Secondary(.18)からMaster(.35)に転送されている様子が見えます。 基本的にはMultiSiteはこんな感じです 今回はCeph Nanoを使って一番シンプルな構成でCeph MultiSiteを構成してみました。 通常のCephクラスターでも今回の作業と本質的には同じです。RGWの数が増えたり、poolのplacementの設定が変わるだけですので、構成すること自体はそんなに難しいことではありません。 一般的にサイト間レプリケーションでよくある問題は、転送スピードが出ない問題です。転送スピードはサイト間のネットワークに依存するところが大きいのですが、スペック上の帯域幅は分かっていても実際にどれくらいの速度が出るかは、やってみないと正直誰も分かりません。私はおろかネットワーク事業者さんも断言はできないでしょう。 ですので、CephでMultiSiteをやってみようと思っている方は、一旦Ceph Nanoを使ってどれくらいの転送ができるのかを試してみることをお勧めします。 というわけで、今回はここまで。
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 Combining Apache Kafka and the Rest client の翻訳記事です。 今週もまた面白い質問がありました。今週は、Kafka と Rest Client の組み合わせについて誰かに聞かれました。それは繰り返しになりますが、ほとんどの場合、次のようなプロセスを目標にしています。 つまり、受信した Kafka メッセージごとにリモートサービスを呼び出したいのです。そのため、読み取りしているデータを含む最初のトピック(「in」)、例えば「トランザクション」があります。次に、アーキテクチャの中心的な部分があります。それは処理コンポーネント(図のProcessing Compornent)です。これは、着信したトランザクションを読み取り、それらのそれぞれについて、リモートサービスを呼び出します。また、それは(リモートサービスによって生成された)レスポンスを別の Kafka トピック "out" に書き込みます。 Quarkus でこれを実装するのは簡単です。この記事ではそれについて説明します。Reactive Messaging と Rest Client のおかげで、これには 20 行以上のコードを必要としません。 リモートサービス まずはリモートサービスから始めてみましょう。Quarkus には、リモート HTTP サービスを呼び出すための複数の方法があります。ですが、HTTP の低レベルの詳細を処理することなく HTTP サービスと対話する優れた方法を提供しているので、Rest Client を使用してみましょう。 みなさんは HTTP API を使うこともできます。ですが、シンプルに言うと、簡単なリモートサービスを考えてみましょう。次のようになります。 @RegisterRestClient(configKey = "transaction-service" ) @Produces(MediaType.APPLICATION\_JSON) @Consumes(MediaType.APPLICATION\_JSON) public interface TransactionService { @Path( "/transactions" ) @POST TransactionResult postSync(Transaction transaction); @Path( "/transactions" ) @POST Uni<TransactionResult> postAsync(Transaction transaction); } このサービスには、同じ HTTP エンドポイントを呼び出す 2 つのメソッドが含まれています。最初のものは同期的なものです。そのため、応答を受け取るまで呼び出し元のスレッドをブロックします。2つ目は非同期です。返された Uni は受信時にレスポンスを取得します。この場合、呼び出し元のスレッドはブロックされません。そのため、他のことができます。これらのメソッドの使い方は後ほど見ていきます。まずは、その前に少し設定を見ましょう。 application.properties に追加します。 # Configure the transaction-service (rest client) transaction-service/mp-rest/url=http://localhost:8080 もちろん、URLを更新します。 https://quarkus.io/guides/rest-client では、Rest Client の使用方法や設定について詳しく説明しています。 着信トランザクションごとにサービスを呼び出す OK、私たちはサービスを呼び出すことはできます。ですが、覚えておいて下さい。私たちはそれを着信トランザクションごとに呼び出したいのです。そしてこれらのトランザクションは Kafka のトピックから来ます。Reactive Messaging を使えば、今すぐに Kafka に対処する必要はありません。私たちはロジックに集中できます。私たちは チャネル (データのストリーム)を持っているとしましょう。これはトランザクションを転送するための物です。これを最初のチャンネル in と呼びます。 また、私たちはリモートサービスからのレスポンスを別の Kafka トピックに書き込みたいと思います。再度言いますが、Kafka に対処する必要はありません。レスポンスを out という名前のチャンネルに書き込んだとします。 そこで、以下のような(不完全な)コードがあります: @ApplicationScoped public class TransactionProcessor { @Incoming( "in" ) // 最初のチャネル - 私たちはそこから読み込む @Outgoing( "out" ) // 2 つ目のチャネル - 私たちはそこへ書込む public TransactionResult sendToTransactionService(Transaction transaction) { // ここで私たちのサービスを読み出す必要がある } } @Incoming は読み込みチャンネルを設定します。 @Outgoing は書き込みチャンネルを設定します。しかし、何かが足りないです...。 私たちはリモートサービスを呼び出す必要があります @ApplicationScoped public class TransactionProcessor { private static final Logger LOGGER = Logger.getLogger( "TransactionProcessor" ); @Inject @RestClient TransactionService service; @Incoming( "in" ) @Outgoing( "out" ) @Blocking public TransactionResult sendToTransactionService(Transaction transaction) { LOGGER.infof( "Sending %s transaction service" , transaction); return service.postSync(transaction); } } まず最初に、Rest Client を注入します。そして、私たちのメソッドの中でそれを呼び出すだけです。 @Blocking について疑問に思うことがあるかもしれません。リアクティブメッセージングでは、ブロッキングコードを使用している場合はその旨を示す必要があります。デフォルトではそれはイベントループアーキテクチャが使用されているためです。便利な反面、 @Blocking を乱用すべきではありません。それは、スレッドプールに依存して同時実行性が制限されるためです。しかし、それはあなたのロジックを同期させます。 非同期操作の使用 TransactionService が実行する 2 番目のメソッド postAsync を使用することで、私たちは @Blocking アノテーションを取り除けます。 @ApplicationScoped public class TransactionProcessor { private static final Logger LOGGER = Logger.getLogger( "TransactionProcessor" ); @Inject @RestClient TransactionService service; @Incoming( "in" ) @Outgoing( "out" ) public Uni<TransactionResult> sendToTransactionService(Transaction transaction) { LOGGER.infof( "Sending %s transaction service" , transaction); return service.postAsync(transaction); } } post メソッドの async バリアントを使用すると、 @Blocking を削除できます。 Uni を直接返します。その Uni はリモートサービスの応答を受信すると、その値を out チャネルに書き込みます。 チャネルを Kafka にマッピング ここまでは順調です。私たちのコードを Kafka に接続する時が来ました。リアクティブメッセージングでは、チャネルをコネクタにマッピングします。ここでは Kafka です。そこで、 in チャンネルと out チャンネルが Kafka のトピックであることを示すようにアプリケーションを設定する必要があります。もう一度、 application.properties ファイルを編集し、追加します。 mp.messaging.incoming.in.connector=smallrye-kafka mp.messaging.incoming.in.topic=transactions mp.messaging.incoming.in.value.deserializer=org.acme.model.TransactionDeserializer mp.messaging.incoming.in.auto.offset.reset=earliest mp.messaging.incoming.in.enable.auto.commit=false mp.messaging.outgoing.out.connector=smallrye-kafka mp.messaging.outgoing.out.topic=output mp.messaging.outgoing.out.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer 最初のブロックは in チャンネルについてです。 それは transactions Kafkaのトピックに接続します。データは カスタムデシリアライザ でデシリアライズされます。最後の他のプロパティは、オートコミット(Reactive Messaging が代わりにコミットを処理してくれます)を無効にします。そして、最後にコミットされたオフセット以降のデータを読み込みます。 2 番目のブロックでは、 out チャネルを設定します。 output Kafkaトピックと接続します。そして、値のシリアライザを設定します。この簡単な例では、データをJSONで書きます。 トランザクションが Kafka transaction トピックに書き込まれると、それは私たちの処理コンポーネントで受信されます。そして、リモートサービスに送信され、その結果が output Kafka トピックに書き込まれます。 2020-08-27 10:04:44,141 INFO [TransactionProcessor] (vert.x-eventloop-thread-0) Sending Transaction{name='MacroHard', amount=20} transaction service 2020-08-27 10:04:44,196 INFO [TransactionResource] (executor-thread-2) Handling transaction MacroHard / 20 2020-08-27 10:04:44,240 INFO [TransactionProcessor] (vert.x-eventloop-thread-0) Sending Transaction{name='BlueHat', amount=10} transaction service 2020-08-27 10:04:44,245 INFO [TransactionResource] (executor-thread-2) Handling transaction BlueHat / 10 output トピックの中を見てみると、 TransactionResult が流れているのが確認できます。 終わりました! 数行のコードと少しの設定で、Kafka トピックからデータを読み取り、リモートサービスを呼び出し、その結果を別の Kafka トピックに書き込めます。単純な話です。 自分でやってみたいと思いますか?この GitHub リポジトリ のコードをチェックアウトして、readme の指示に従ってください。 Reactive Messaging と Rest クライアントには他にも宝石が含まれています。関連するガイドやドキュメントを確認して詳細を確認してください。 Restクライアントの使用 Kafka との対話 Kafka Connector のドキュメント
この投稿は「 Rookと仲間たち、クラウドネイティブなストレージの Advent Calendar 2020 - Qiita 」の 2 日目の記事です。 レッドハットでコンサルタントをしている金子です。Rook Test Framework を実行する環境の構築とテストの実施について記載します。 Advent Calendar は始まったばかりですが、他の投稿記事は以下から参照できます。ぜひ御覧ください。 qiita.com Rook Test Framework とは 公式のドキュメント に次の通り記載されていますが、Rook のコンテナイメージを実際にビルドし、エンドツーエンドのテストを実施するためのフレームワークが提供として提供されています。 The Rook Test Framework is used to run end to end and integration tests on Rook. The framework depends on a running instance of Kubernetes. The framework also provides scripts for starting Kubernetes using kubeadm or minikube so users can quickly spin up a Kubernetes cluster.The Test framework is designed to install Rook, run tests, and uninstall Rook. テストには Kubernetes の環境が必要なため、 kubeadm や minikube を利用して環境を構築した上で、予めビルドした Rook イメージに対してテストを実施します。今後、Rook を利用した際に見つけた不具合などを修正するなどのコミュニティ活動を行う上で参考にしていただければと思います。 環境概要 テスト要件は次のとおりとなります。実行環境は Ubuntu 18 となります。テスト用のストレージデバイスの準備のしやすさなどから、今回は VirtualBox 上に環境を構築しテストを実行します。 Package Version 備考 Docker 1.2 && < 17.0 docker 以外を利用する場合は、環境変数 DOCKERCMD にコマンドラインツールを指定してください Ubuntu 18 現在のテストは本バージョンのみで動作確認が行われています。 kernel >= 4.15 - Kubernetes with kubectl >= 1.15 新しいバージョンの環境でテストを実施したい場合は、環境変数 KUBE_VERSION にバージョンを指定してください。例:KUBE_VERSION=v1.19.0 Rook - 事前にビルドする必要があります。 環境準備 VirtualBox 環境の準備 今回作成した環境では VirtualBox と vagrant を利用します。インストールは予め済ませておいてください。 vagrant init で作成するデフォルトの VM ではディスクサイズが小さいためルートボリュームのサイズを少し増やしておきます。 利用した Vagrantfile は次のとおりです。ルートボリュームを拡張するため、事前に vagrant には以下のコマンドでプラグインをインストールしておきます。 $ vagrant plugin install vagrant-disksize Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.provider "virtualbox" do |v| v.name = "rook" end config.vm.box = "ubuntu/bionic64" config.disksize.size = '200GB' end 一度 VM を作成した後、ストレージデバイスをアタッチするため停止します。 $ vagrant init Bringing machine 'default' up with 'virtualbox' provider... ==> default: Importing base box 'ubuntu/bionic64'... ==> default: Matching MAC address for NAT networking... ==> default: Checking if box 'ubuntu/bionic64' version '20201014.0.0' is up to date... ==> default: A newer version of the box 'ubuntu/bionic64' for provider 'virtualbox' is ==> default: available! You currently have version '20201014.0.0'. The latest is version ... default: your host and reload your VM. default: default: Guest Additions Version: 5.2.42 default: VirtualBox Version: 6.1 ==> default: Mounting shared folders... default: /vagrant => /home/cloud-user/virtualbox/rook $ vagrant halt ==> default: Attempting graceful shutdown of VM... テスト実行中に利用するデバイスを作成した VM にアタッチします。ディスクサイズは 5GB ほどあれば十分なようですが念の為多めに 20GB 用意します。 ゲストOSからは、デバイスは /dev/sdb として参照できるようになります。 また、CPUやメモリリソースに余裕がある場合は、テスト実行時間を短縮するためリソースを拡張しておきます。 $ vboxmanage createhd --filename extra_disk.vdi --size 200000 --format VDI $ vboxmanage storageattach rook --storagectl "SCSI" --device 0 --port 2 --type hdd --medium extra_disk.vdi $ vboxmanage modifyvm rook2 --cpus 4 --memory 8096 デバイスが VM にアタッチできていることを確認します。先程作成したデバイスが SCSI (2,0) としてアタッチされていることが確認できます。 $ vboxmanage showvminfo rook | grep SCSI Storage Controller Name (1): SCSI SCSI (0, 0): /home/cloud-user/VirtualBox VMs/rook/ubuntu-bionic-18.04-cloudimg.vdi (UUID: 864cc634-ac60-48e6-9d1e-22dec83ef55e) SCSI (1, 0): /home/cloud-user/VirtualBox VMs/rook/ubuntu-bionic-18.04-cloudimg-configdrive.vmdk (UUID: 5ea3cce8-1695-4074-9859-98b8485fff8a) SCSI (2, 0): /home/cloud-user/virtualbox/rook/extra_disk.vdi (UUID: e1a7d106-4363-4f59-847e-08f6706e2b0c) VM  を起動し、VM上で環境構築を継続します。 $ vagrant up $ vagrant ssh パッケージのインストール Rook のイメージのビルド、Kubernetes 上でのテスト実施のために、以下のパッケージをインストールします。 docker-ce make go make のインストール # apt-get install -y install build-essential docker, go のインストールについては、ドキュメントを参照してください。 Install Docker Engine on Ubuntu | Docker Documentation Download and install - The Go Programming Language Rook ビルド環境の準備 Rook リポジトリ を clone します。GOPATH の関係などから、 $HOME/go/src/github.com/rook/ に clone します。 # mkdir -p $HOME/go/src/github.com/rook # export GOPATH=$HOME/go # cd $HOME/go/src/github.com/rook # git clone https://github.com/rook/rook.git ひとまず、テストを実施するのみなので master ブランチで作業を行います。 Rook イメージのビルド ドキュメント に従い、ビルドを実行します。 # cd $HOME/go/src/github.com/rook/rook # make -j4 実行が完了すると最後に以下のようなメッセージが出力されることを確認してください。 ... Congratulations! Your Rook CSV 9999.9999.9999 manifest for k8s is ready at: cluster/olm/ceph/deploy/olm-catalog/k8s/9999.9999.9999/manifests Push it to https://github.com/operator-framework/community-operators as well as the CRDs from the same folder and the package file cluster/olm/ceph/assemble/rook-ceph.package.yaml. Template stored at cluster/olm/ceph/templates/rook-ceph-k8s.vVERSION.clusterserviceversion.yaml.in === container build build-a7ad6610/ceph-amd64 sha256:3d0c8ef6a1b96d36259cd98de569a9563612a3907352e9568159a10b7764e690 sha256:5d54aa21ff9fca46acacf22b4b605282be4e5c81cbed8e8799b7f047b4ef1a94 === saving image build-a7ad6610/edgefs-amd64 === container build build-a7ad6610/yugabytedb-amd64 sha256:adfc420992ca25c37b667c0f66b664c0c658403749386e4e3a8c3a9a716ee01d sha256:14c0204aa0f71566ac6a7efc06f0045034e9bc3158c7c90d4104362d37692e5c sha256:5a593be97f73071649d42175479c432af82ef7d08823dd26a552dd60a7e8bcea === saving image build-a7ad6610/nfs-amd64 Rook Test Framework を使ったインテグレーションテストの実行 環境がクリーンであるか確認 準備が整ったため、テストを実施します。実施前に環境がクリーンであるか確認します。確認方法は rook の ドキュメント をベースにチェックします。 確認の概要としては、Kubernetes がクリーンな状態であるかどうか、Rook が利用するデバイス(本環境では /dev/sdb ) が 0x00 で初期化されていることの確認をします。 Kubernetes 環境はまだ立ち上げていないため、これから準備する環境はクリーンではありますが、ディスクを確認しておきます。次のコマンドを実行し、デバイスが 0x00 で初期化されていることを確認してください。 # xxd -l 128 /dev/sdb 00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 万が一、ディスクが初期化されていない場合は、Rook メンテナーである satoru-takeuchi さんのリポジトリにある ci-fini.sh を参考に、ディスクを初期化します。 デバイスは環境に合わせて変更してください。本記事に従った場合は /dev/sdb が対象のデバイスとなっているはずです。 # export TEST_SCRATCH_DEVICE=/dev/sdb # vgremove --yes --force rook-integration-test-vg # pvremove --yes --force ${TEST_SCRATCH_DEVICE} # dd if=/dev/zero of=${TEST_SCRATCH_DEVICE} bs=1M count=100 oflag=dsync,direct kubeadm を利用した環境の準備 エンドツーエンドの実行環境を構築します。 # tests/scripts/kubeadm.sh up # export KUBECONFIG=~/admin.conf # tests/scripts/helm.sh up 環境に正常にアクセスできることを確認します。Node の Status が Ready となっていること、Kubernetes のバージョンが取得できていることを確認します。 # kubectl get node NAME STATUS ROLES AGE VERSION ubuntu-bionic Ready master 112s v1.15.12 # kubectl version Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.4", GitCommit:"d360454c9bcd1634cf4cc52d1867af5491dc9c5f", GitTreeState:"clean", BuildDate:"2020-11-11T13:17:17Z", GoVersion:"go1.15.2", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.12", GitCommit:"e2a822d9f3c2fdb5c9bfbe64313cf9f657f0a725", GitTreeState:"clean", BuildDate:"2020-05-06T05:09:48Z", GoVersion:"go1.12.17", Compiler:"gc", Platform:"linux/amd64"} テスト実施に必要な環境変数を設定します。 # export TEST_HELM_PATH=/tmp/rook-tests-scripts-helm/linux-amd64/helm # export TEST_BASE_DIR=/tmp/rook-integration # export TEST_SCRATCH_DEVICE=/dev/sdb # mkdir -p $TEST_BASE_DIR テストの実行 すべてのテストを最初から実行すると、環境が正しく出来ているかわからないため、一部のテストを実行して確認します。ドキュメントにある TestARookClusterInstallation_SmokeTest を実行します。 # go test -v -timeout 1800s -run CephSmokeSuite github.com/rook/rook/tests/integration -testify.m TestARookClusterInstallation_SmokeTest 以下のように出力されれば準備完了です。 ... 2020-11-29 13:53:34.086285 I | installer: verifying clean up of /tmp/rook-integration/rook-test from node ubuntu-bionic. err=<nil> 2020-11-29 13:53:34.088708 I | installer: system namespace "smoke-ns-system" still found... 2020-11-29 13:53:39.092630 I | installer: system namespace "smoke-ns-system" still found... 2020-11-29 13:53:44.096048 I | installer: system namespace "smoke-ns-system" still found... 2020-11-29 13:53:49.395553 I | installer: system namespace "smoke-ns-system" removed --- PASS: TestCephSmokeSuite (184.87s) --- PASS: TestCephSmokeSuite/TestARookClusterInstallation_SmokeTest (5.09s) PASS ok github.com/rook/rook/tests/integration 184.900s 準備が出来ていますので、テストを実行しましょう。 # go test -v -timeout 7200s github.com/rook/rook/tests/integration まとめ 実行環境は準備できたでしょうか。テスト環境を構築できれば、今後 Rook に対してなにか修正を提供する機会があったときにテストが実行できるためコミュニティ活動がやりやすくなるかと思います。 実際に修正を提供する場合には、コミットメッセージを含めてコミュニティのルールが存在するため、以下のドキュメントを予め参照してから修正するとスムーズかと思います。 github.com 参考ですが、Rook リポジトリへ Pull Request を作成するときにチェックすべきチェックリストは次のとおりです。 事前に以下のドキュメントには目を通しておけば、チェックリストには回答できるかと思います。 https://rook.io/docs/rook/master/development-flow.html https://github.com/rook/rook/blob/master/INSTALL.md Checklist: - Commit Message Formatting: Commit titles and messages follow guidelines in the developer guide. - Skip Tests for Docs: Add the flag for skipping the build if this is only a documentation change. See here for the flag. - Skip Unrelated Tests: Add a flag to run tests for a specific storage provider. See test options. - Reviewed the developer guide on Submitting a Pull Request - Documentation has been updated, if necessary. - Unit tests have been added, if necessary. - Integration tests have been added, if necessary. - Pending release notes updated with breaking and/or notable changes, if necessary. - Upgrade from previous release is tested and upgrade user guide is updated, if necessary. - Code generation (make codegen) has been run to update object specifications, if necessary. 注意事項 Rook Test Framework はテスト実施後に環境をクリーンにするための処理も実装されていますが、発生した異常によってはクリーンにならないこともあるようです。例えば、テスト実施時に設定したタイムアウト時間を超えてしまった場合は強制的にテストが終了してしまうため、終了処理が実施されません。その場合は、環境構築時に実施したディスクを初期化するコマンドと、Kubernetes を再作成することをおすすめします。 Kubernetes の初期化はコマンドが用意されており、以下を実行するのみとなります。 # tests/scripts/kubeadm.sh clean 再度テストを実施する場合は、 tests/scripts/kubeadm.sh up の手順から実施することでクリーンな環境でテストを行うことが出来ます。 参考 rook/tests at master · rook/rook · GitHub Install Docker Engine on Ubuntu | Docker Documentation Download and install - The Go Programming Language rook-helper/ci-fini.sh at master · satoru-takeuchi/rook-helper · GitHub
みなさんこんにちは。レッドハットの杉村です。Ansible のテクニカルサポートをしています。 米国時間の11月18日、Red Hat Ansible Automation Platform 1.2 がリリースされました。Ansible Tower 3.8.0 と Automation Hub 4.2.0 を同梱しています。 Red Hat Ansible Automation Platform Release Notes 今回の記事では、この Automation Hub について紹介します。 Automation Hub とは これまで Collections としてさまざまなロールやモジュールを SaaS サービスの cloud.redhat.com から配布してきました。 今回リリースされた Automation Hub では、Collections をインターネットへの接続がなく閉じた環境からでも利用したいということや、社内だけで使う Collections を配布したいといった用途にお使いいただけるものとなっています。 Automation Hub のインストール Automation Hub は Ansible Tower 3.8.0 と一緒に配布されています。 inventory ファイルにこのような項目が追加されていて、Tower と同時にインストールすることができます。いろいろと設定値があるように見えますが、インストール先とDBの接続情報、初期パスワードを設定するものとなっています。 インストールは同時に実施いただけるのですが、Automation Hub をインストールするサーバは Tower と同居させることはできません。データベースもサーバを Tower でお使いのものと分離することをお勧めしますが、検証等で同居させる場合であっても、automationhub_pg_database は pg_database の設定とは分けるようにしてください。 Tower がすでに導入されている場合でも、Automation Hub を後から追加することができます。 [automationhub] 192.168.0.102 [all:vars] automationhub_admin_password='XXXXXXXX' automationhub_pg_host='192.168.0.101' automationhub_pg_port='5432' automationhub_pg_database='automationhub' automationhub_pg_username='automationhub' automationhub_pg_password='XXXXXXXX' automationhub_pg_sslmode='prefer' # automationhub_upgrade = False # automationhub_require_content_approval = True # automationhub_importer_settings = None # automationhub_disable_https = False # automationhub_disable_hsts = False # automationhub_ssl_validate_certs = False # automationhub_ssl_cert=/path/to/automationhub.cert # automationhub_ssl_key=/path/to/automationhub.key Tower と同じようにインストーラを起動すると、プレイブックが動作してインストールされます。 # ./setup.sh 無事正常終了したら、Web ブラウザから admin ユーザでログインしてみてください。 Automation Hub の設定 社内に閉じた環境に Collections を提供するということを想定して、cloud.redhat.com から Collections を同期してみることにします。 cloud.redhat.com にログインしていただきますと、このような画面になります。Red Hat Ansible Automation Platform の四角いパネルの中にある、Automation Hub をクリックします。 Connect To Hub のメニューを開きますと、接続のための情報が出てきます。 Load Token のボタンを押して、Token の値をメモします。この Token や URL の情報を使って、Automation Hub から接続します。 この cloud.redhat.com から提供されている Collections は、Ansible Engine からも使うことができます。 ansible.cfg にこのように設定します。 [galaxy] server_list = automation_hub [galaxy_server.automation_hub] url=https://cloud.redhat.com/api/automation-hub/ auth_url=https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token token=<Tokenの文字列> 詳しくはこちらのドキュメントをご覧ください。 docs.ansible.com Automation Hub に戻りまして、Repo Management のメニューを開きます。Local と Remote がありますが、Remote を開いて、rh-certified の列で一番右にある設定から Edit を押します。 cloud.redhat.com で取得した Token をこの欄に入力して、Save を押して保存します。 Sync のボタンを押しますと、同期処理が始まります。 もし失敗したときは、この Automation Hub をインストールしたサーバの /var/log/messages にログが記録されるので確認してみてください。わたしの環境では、なぜか Chrome では Token のコピーが正しく行われないようで、Firefox で実行するとうまくできました。 Nov 30 15:08:16 localhost rq: pulp: pulp_ansible.app.downloaders:INFO: Updating bearer token のようなエラーが出ているときは Token が正しくないと判断されていますので、何度か入れ直してみてください。 無事同期が終わりますとこのように Completed となります。 左のメニューから Red Hat Cerfified を選んで、Collections を開くとこのように cloud.redhat.com で見たものと同じように取り込まれていることが確認できます。このとき、アイコンは残念ながら同期されないようです。 Ansible Tower からの利用 この同期した Automation Hub に対して、Ansible Tower から接続して Collections を取ってきて使うということをしてみます。例としてはあまりいいものではないかもしれませんが、ansible.tower を使ってみることにします。 プロジェクトを作成 まずプロジェクトを作成します。playbook を書いて、github に保存しました。「手動 (manual)」プロジェクトではなく SCM を使うようにしてください。 ファイルを2つ作ります。 playbook.yml ansible.tower.tower_job_launch モジュールを使って、Tower のジョブを起動するというものを作ってみました。 --- - hosts: all gather_facts: false collections: - ansible.tower tasks: - name: Launch a job tower_job_launch: job_template: "Demo Job Template" tower_host: 192.168.0.100 tower_username: user46 tower_password: XXXXXXXX validate_certs: false collections/requirements.yml Private Automation Hub にある ansible.tower を使いますよということを宣言します。この collections/requirements.yml に書いておくことで、プロジェクトを Tower が同期したときに一緒に取ってくるようになります。 --- collections: - name: ansible.tower version: 3.8.0 source: https://192.168.0.102/api/galaxy/content/rh-certified/ この source: で指定する URL は、Repo Management の rh-certified の列にある Repo URL から取得して使います。 このとき、API Token も取得しておいてください。 左のメニューから API Token を開いて、Load Token のボタンを押します。 認証情報を作成 Tower から Automation Hub にアクセスするための認証情報を作成します。 認証情報タイプは「Ansible Galaxy/Automation Hub API トークン」です。 GALAXY SERVER URL: https://192.168.0.102/api/galaxy/content/rh-certified/ API トークン: <先ほど取得したTokenの文字列> を設定して保存します。 この認証情報は、「組織」に設定します。ここでは「組織」の「Default」に設定しました。 プロジェクトを同期 ここまでできたら、プロジェクトの同期ができるようになります。github からプロジェクトを同期してくるよう設定して、「最新SCMリビジョンの取得」のアイコンをクリックすると git clone のような処理を実行します。このとき、Tower はプロジェクトに含まれる collections/requirements.yml ファイルが存在することを確認して、内部的に ansible-galaxy コマンドを実行して Collections も取得してきます。 ジョブを実行 このプロジェクトを使うジョブテンプレートを作成して、ジョブを実行します。 実際にジョブが実行されて成功したことも確認してみてください。 少々ややこしくなりますが、このジョブから実行されたプレイブックは Tower のジョブテンプレートを user46 ユーザで実行するものでした。そちらのログも確認してみると、正しく実行されていることがわかります。 まとめ Automation Hub を導入して、そこに格納されている Collections を Ansible Tower から利用してみるための方法について紹介しました。 今後 Collections としてロールやモジュールを再利用していくことが増えてきます。弊社が提供する SaaS の cloud.redhat.com で共有するのがさまざまな理由で難しい場合には、お手元で Automation Hub を建てていただくことで、Collections の機能を閉じた環境でも利用できるようになります。 Ansible Towerの評価ライセンスリクエストはこちらからご利用いただけます。 www.redhat.com Happy Automation!
Red Hatソリューションアーキテクトの小島です。 Red Hat Enterprise Linux (RHEL) 8からはRHEL7で導入されたDocker技術が削除され、Podman, Buildah, Skopeoなどの新しいコンテナ技術が導入されました。PodmanとBuildahについては赤帽エンジニアブログの 他の記事で既に紹介 されていますが、ここではPodman, Buildah, UBI (RHELをベースにした無償提供のコンテナイメージ)の具体的な利用手順を、スライド(P.7~)にまとめています。また、Red Hat Developer Programに参加して開発者向けの無償サブスクリプションを入手することで、これらの手順を無料で試してみることができます。Red Hat Developer Programについては下記の記事も参考にしてください。 rheb.hatenablog.com ↓利用手順例(コピペ用) Podmanのインストール $ sudo subscription-manager register $ sudo subscription-manager attach --auto $ sudo yum -y install podman $ sudo yum -y install podman-docker <- podman-dockerは、dockerという名前でpodmanコマンドへのシンボリックリンクを作成するためのパッケージ(オプション) Podmanの利用例 $ podman pull registry.access.redhat.com/ubi8/ubi:latest $ podman run --name test01 -it registry.access.redhat.com/ubi8/ubi:latest /bin/bash [root@c21ad143c67f /]# yum -y install httpd [root@c21ad143c67f /]# exit $ podman ps -a CONTAINER ID IMAGE COMMAND CREATED NAMES aeb95fb38a18 registry.access.redhat.com/ubi8/ubi:latest /bin/bash 38 seconds ago test01 $ podman start -ai test01 [root@aeb95fb38a18 /]# exit $ podman commit test01 httpd_ubi_01 $ podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/httpd_ubi_01 latest d610cfd1a46f About a minute ago 242 MB registry.access.redhat.com/ubi8/ubi latest ecbc6f53bba0 2 weeks ago 211 MB UBIとDockerfileを利用したコンテナイメージの作成例 $ cat << EOF > myecho > echo "This container works!!" > EOF $ cat << EOF > Dockerfile > FROM registry.access.redhat.com/ubi8/ubi > ADD myecho /usr/local/bin > ENTRYPOINT "/usr/local/bin/myecho" > EOF $ chmod +x myecho $ ./myecho This container works!! $ ls Dockerfile myecho $ podman build . STEP 1: FROM registry.access.redhat.com/ubi8/ubi ... Storing signatures STEP 2: ADD myecho /usr/local/bin 9f842e451aeb46b0852a33362f0632d182008631e30ead39fa03bbd5ac8eb18f STEP 3: ENTRYPOINT "/usr/local/bin/myecho" STEP 4: COMMIT 0db4e77ef97e260c24129434881a51d06dcb32f5f38aaecf193aca62aa60c890 $ podman images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 0db4e77ef97e 2 minutes ago 211 MB registry.access.redhat.com/ubi8/ubi latest ecbc6f53bba0 2 weeks ago 211 MB Red Hat Quay.io (無料かつ無制限に利用可能なパブリックレジストリのSaaSを提供)へのイメージのpush例 $ podman login quay.io Username: <your_user_name> Password: <your_password> Login Succeeded! $ podman images $ podman tag <作成したイメージのContainer ID> quay.io/<your_user_name>/myecho $ podman push quay.io/<your_user_name>/myecho Buildahのインストールと利用例 $ sudo yum -y install buildah $ buildah from scratch <- 「working-container」という名前のscratchコンテナを作成 working-container $ buildah unshare <- 特権ユーザの権限を利用して、コンテナのrootファイルシステムをユーザのホームディレクトリの中にマウントできるようになります # scratchmnt=$(buildah mount working-container) <- scratchコンテナのrootファイルシステムをマウント # yum install -y --releasever=8 --installroot=$scratchmnt redhat-release <- scratchコンテナでのRPMデータベースの初期化とredhat-releaseパッケージの追加 # yum install -y --setopt=reposdir=/etc/yum.repos.d \ --installroot=$scratchmnt \ --setopt=cachedir=/tmp/cache/dnf bash <- scratchコンテナへのbashのインストール # echo "echo Your container from scratch worked." > $scratchmnt/usr/local/bin/myecho <- scratchコンテナにmyechoファイルの追加 # chmod +x $scratchmnt/usr/local/bin/myecho # buildah config --entrypoint "/usr/local/bin/myecho" working-container <- コンテナ起動時にmyechoファイルを実行することを指定 # buildah commit working-container localhost/myecho:latest <- scratchコンテナの変更をコミットして「localhost/myecho」イメージを作成 # exit $ podman run localhost/myecho <- buildahで作成したイメージをpodmanで起動 Your container from scratch worked. speakerdeck.com
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 Using Redis with Mutiny - Composing asynchronous actions の翻訳記事です。 ユーザーから Redis と Mutiny について興味深い質問を受けました。この問題は特に Redis に関するものではなく、他の多くの API にも適用できるものでしたが、私はこの文脈が面白いと感じました。 ユーザーの Enrico は、こんなことをしたいと思っていました: 1. Redis からすべてのキーを取得 2. 各キーに対して -> 関連するオブジェクトを取得 3. このオブジェクトを JsonArray に追加 4. すべてのオブジェクトを含む JsonArray を生成 Enrico は Vert.x Redis クライアントの Mutiny 型を使用しています。 このクライアントは、私たちの問題を解決するために、いくつかのメソッドを提供しています。 RedisClient.keys(pattern) メソッドは Uni<JsonArray> を返します。この配列には、 keys メソッドに渡されたパターンに一致するキーのリストが含まれます。この記事を簡単にするために、すべてのキーを返す: keys("*") を使用してみましょう。 RedisClient.hgetall(key) メソッドは Uni<JsonObject> を返します。このメソッドは、渡されたキーに関連付けられたオブジェクトを取得します。 どちらのメソッドも非同期(Uniを返す)です。なので、取得したキーごとに 2 番目のメソッドを呼び出す必要があります。言い換えれば、キーのセットを反復処理し、各キーに対して非同期アクションを呼び出す必要があります。最後に、これらの非同期アクションの結果を JsonArray に収集したいと思います。 まずは最初からやってみましょう;Redis クライアントのインスタンスが必要です。 RedisClient redis = RedisClient.create(vertx, new JsonObject() .put( "port" , 6379 ) .put( "host" , "localhost" )); Quarkus では、Redis 拡張モジュールを直接使用する必要があります。それは同様の API を公開しています。Enrico は Vert.x Redis クライアントを直接使いたいと思っていました。 クライアントを手に入れたので、キーのリストを取得してみましょう。 Uni<JsonArray> keys = redis.keys( "*" ) これは JsonArray を生成します。ですが、キーのストリームが必要です。繰り返しになりますが、これは非同期メソッドです。返された Uni は利用可能なときに配列を受け取ります。( onItem ) を一度受け取ると、この配列からストリームを作成できます。 Multi<String> keys = redis.keys( "*" ) .onItem().transformToMulti(array -> Multi.createFrom().iterable(array)) .onItem().castTo(String. class ); このスニペット: キーを含む JsonArray を取得します。 これらのキーをストリーミングする Multi を作成します。それは JsonArray が Iterable<Object> を拡張しているので Multi<Object> です。 この Multi アイテムを String に対応付けします。 この時点では、(String)キーのストリームがあります。ということで、ステップ1はこれで終了です。 さて、ステップ2:各キーについて、関連するオブジェクトを取得したいと思います。 そこで、 hgetall メソッドを使ってみましょう: Multi<JsonObject> objects = keys .onItem().transformToUniAndMerge(key -> redis.hgetall(key)); このスニペットは少し説明が必要です。 キー のストリームの各アイテムについて、 hgetall を呼び出して Uni<JsonObject> を生成します。 そこで、キーを Uni に変換したいと思います( transformToUni )。 アイテムのストリームがあり、各アイテムに対して非同期アクションを呼び出す必要がある場合、結果をどのようにマージするかを選択しなければなりません。Mutiny は2つの戦略を提供します。 マージ - Uni で生産されたアイテムを受信したらすぐにそれを下流に送ります。 連結 - 入力ストリームの順序を保持して、下流に送られるアイテムが同じ順序で送られるようにします。 これを図解してみましょう。我々はキー 1 、 2 、 3 を持ち、それをストリーム {1、2、3} に持っていると想像してみてください。また、私たちの Redis データベースでは、キー 1 が A 、 2 が B 、 3 が C に関連付けられていると考えてみましょう。 マージ 戦略を使用した場合、関連するオブジェクトを不確定な順序で取得しています。最終的には {A, C, B} または {B, A, C} で終われます。それは、レイテンシ、スケジューリング、負荷など多くの要因に依存します。しかし、これは、関連するすべてのオブジェクトを並列に取得し、順序を気にせずに結果のストリームを生成できることを意味します。 連結 戦略を使用すると、それは入力ストリームからの順序を保持します。なので、必ず {A,B,C} が出てきます。それが望ましいかもしれませんが、それは同時にオブジェクトを取得する能力を低下させる可能性があります。それは、Mutinyが前のオブジェクトのすべての検索を 待た なければならないようなものです。例えば、Mutiny が先に C を受信した場合、C を下流に送る前に A と B を待つ必要があります。 この文脈では、順序を保持せずに マージ 戦略を使用しましょう。そこで、 transformToUniAndMerge を使用します。 コードを何度も実行すると、結果の配列の順序が変わるかもしれません。 ステップ2は完了しました。最後のステップに焦点を当ててみましょう:オブジェクトを JsonArray に蓄積し、すべてのオブジェクトを含む Uni<JsonArray> を生成します。Mutiny はストリームからアイテムをリスト、マップ、セットに収集するメソッドを提供しています。ですが、組み込みの JsonArray のサポートはありません。幸いなことに、Mutiny はあなたがどのような構造のアイテムを収集するためにも使用できるメソッドを提供しています。 Uni<JsonArray> result = objects .collectItems().in(() -> new JsonArray(), (arr, obj) -> arr.add(obj)); collectItems().in は、独自の構造にアイテムを蓄積できます。これは2つのパラメータを取ります。一度だけ呼び出される構造の supplier と、構造と追加するアイテムを受け取る bi-consumer で、各アイテムごとに呼び出されます。 さあ、行きましょう。これで Enrico の疑問を解決できます。 オールインワン のコードは以下の通りです: Uni<JsonArray> result = // ステップ1 - キーを取得 redis.keys( "*" ) .onItem().transformToMulti(keys -> Multi.createFrom().iterable(keys)) .onItem().castTo(String. class ) // ステップ2 - 各キーに関連付けられたオブジェクトを取得 .onItem().transformToUniAndMerge(key -> redis.hgetall(key)) // ステップ3と4 - 取得したオブジェクトをJsonArrayに蓄積 .collectItems().in(() -> new JsonArray(), (arr, obj) -> arr.add(obj)); このスニペットでは、いくつかの面白いパターンがあります: コレクションを持っていて、それを Mutiny で反復したい場合は、それを Multi に変換します。 ストリームの各アイテムに対して非同期アクションを実行する場合、 マージ と 連結 について考えてみてください。自分にとって意味のあるものを使いましょう。 アイテムを構造に蓄積するには、 collectItems を使用します。それはあなたの選択の構造を生成するための多くのメソッドを提供しています。 このコードが実際に動作しているのを見たい場合は、この gist を確認してください。JBang で直接実行することもできます。 jbang https://gist.github.com/cescoffier/e8c8a18897f9e5ca15f1378876a1bd93 merge を concatenate に置き換えると違いがわかります。 楽しもう!
Red Hatのソリューションアーキテクトの暮林です。 Red Hat にはクラウドネイティブアプリの開発に役立つ、Application Services のラインナップが充実していることをご存知ですか? ここでは、Red Hatの Application Services に関する注目ニュースを、各製品技術に特化したソリューションアーキテクトが、ご紹介します。 今回は 12 月号となります。 想定読者 エンタープライズアーキテクト アプリケーション開発者 システムの提案をするSIerの方 特集1:そろそろやるか? Red Hatの「オンプレからのモダナイゼーションソリューション」いろいろ 最近は金融機関や通信企業で頻繁に相談に乗って欲しいという気概が増えたアプリケーションのモダナイゼーション。 ビジネスの敏捷性を高め、システムの可用性も高く、かつ低コストで実現する方法が求められています。 これらについて簡単に実現しやすいソリューションを集めてみました。 speakerdeck.com 特集2:今注目の「イベント駆動アーキテクチャ」を理解する! Red Hatの最新ソリューションを紹介 Iot、AI、マシン、人など、様々なイベントソースからデータが大量に生成されるようになり、それをリアルタイムに処理する必要性からイベント駆動アーキテクチャに注目が集まっています。 今回はイベント駆動アーキテクチャの基本的なことからRed Hatが提供するApache Kafkaを含めたRed Hat Integrationをベースとしたソリューションについても紹介しています。 speakerdeck.com 特集3:ビジネス上の意思決定とプロセスを自動化する Red Hat Process Automation の最新アップデート特集 Red Hat Process Automation 7.9が、11/6にGAとなりました! このリリースでは、主に今回のリリースでは、アプリケーションやビジネスダッシュボードの作成を高速化するために、 開発者やユーザーエクスペリエンスの改善に主眼を置いています。 今回はその新機能の中から、以下についてご紹介していきます。 Rules performance analysys ルール実行中のボトルネックの分析と識別についての新しい機能が追加されました。 Kafka out-of-the-box integration Red Hat Process Automation Manager は、kafka と統合し、ユーザーが kafka のトピックにイベントを送信するためのタスクを使用できるようになりました。 Revamp in Business Analysis and Monitoring Dashbordコンポーネントが、standaloneのコンポーネントとしてサポートされるようになりました。 speakerdeck.com 好評開催中!クラウドネイティブアプリ開発関連のWebinar全6回 Cloud Nativeを見据えたアプリケーションアーキテクチャとレガシーモダナイゼーション コンテナ時代の開発ツールチェインと開発プロセスのベストプラクティス クラウド/コンテナを前提とした時代のアプリケーション実行環境の選択 マイクロサービス/サーバーレス実践入門 これからのシステム連携を実現するデジタル基盤とアプローチ Cloud Nativeなデータパイプラインの作り方とオープンハイブリッドクラウドへの展開 各回とも、オンデマンドで視聴出来ます。(お名前とメールアドレス等の登録のみで視聴可能です) 下記リンクよりぜひご登録ください。 www.redhat.com 直近GAになった製品群 最近リリースとなった Application Services 製品群のリストをご紹介します。 見逃している製品が無いか、是非一度ご確認ください。 Red Hat AMQ Online 1.6 Red Hat Process Automation Manager 7.9
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 Quarkus 1.9 released - Micrometer extension maturing, multiple Redis clients, Quarkiverse の翻訳記事です。 Quarkus 1.9 では、既存の機能セットに加えて、多くの改良が加えられています。 Micrometer の拡張機能が成熟 Kafka がメトリクスを持つ 複数のRedisクライアントがサポート(Sentinel接続と同様) Reactive Routes で Bean Validation をサポート SmallRye Reactive Messaging が 2.4.0 に、Mutiny が 0.9.0 にアップグレード いつものように、バグ修正や使い勝手の改善、ドキュメントの改善なども行われています。 最後になりましたが、 The Quarkiverse initiative も始めました。 移行ガイド 既存のアプリケーションの移行をお考えですか?こちらが 1.9への移行ガイド です。 最大の変更点は、1.3 で非推奨になった古いデータソース(JDBC と reactive)の設定がなくなったことです。もしデータソースが動かなくなった場合は、新しい設定にまだ移行していないことが原因でしょう。 Java 11 風の GraalVM 20.2 が推奨の GraalVM のバージョンです。 何が新しいの? Micrometer の拡張機能が成熟 1.8 は新しい Micrometer 拡張機能を導入しました。1.9 の開発サイクルの間に多くの成熟を遂げ、現在では Quarkus でメトリクスを収集するための推奨される方法となっています。 例えば、Kafka のメトリクスを取得できるようになりました。 Bean Validation と Reactive Routes Bean Validation 制約が Reactive Routes メソッドのパラメータと戻り値( Uni はサポートされていますが、 Multi はサポートされていません)に考慮されるようになりました。 さらなる Reactive の変更 SmallRye Reactive Messaging は 2.4.0 にアップグレードされました。これはいくつかの改善が含まれています。Kafka のクラウドイベントのサポート、バグ修正、Mutiny の 0.9.0 への変更などです。 プルリクエスト記述 に主な変更点が記載されています。 quarkus-rest-client-mutiny 拡張機能のおかげで、REST クライアントで Mutiny を使うことがこれまで以上に簡単になりました。 @TestTransaction アノテーション このアノテーションは、コミュニティからの定期的なリクエストへの対応です:テストで行われた変更をロールバックする機能を持つことです。 テストに @Transactional というアノテーションを付ける(これは変更を永続化させます)代わりに、テストに @TestTransaction というアノテーションを付けると、テストの終了時に変更が自動的にロールバックされます。 複数の Redis クライアント 今までは1つの Redis インスタンスにしか接続できませんでした。 1.9 からは、複数のインスタンスに接続できるようになりました。また、Sentinel もサポートされるようになりました。 その他の変更点 今は JAXP の拡張機能を別に持ちます。今までこれは JAXB の拡張機能に織り込まれていました。 Hibernate ORM が 5.4.22.Final に、Hibernate Reactive が 1.0.0.Alpha10 にアップグレードされました。 完全な変更ログ 1.9.0.CR1 と 1.9.0.Final の完全な変更ログはGitHubで入手できます。 Quarkiverse もし拡張機能のエコシステムがなければ、Quarkus はこれほどの成功を収められなかったでしょう。当初は、すべての拡張機能をコアの Quarkus リポジトリに追加していました。ですが、最終的にはオーバーヘッドが大きすぎたり、コアに拡張機能を含めることが必ずしも賢明とは限らないものになってしまいました。その後、Quarkus の外部に独自のリポジトリを作成した人もいますが、そうでない人もいます。誰もがビルドセットアップを維持するためのオーバーヘッドを望んでいるわけではないからです。他のケースでは、実際には拡張機能のアイデアがあったものの、コアに含めるにはまだ十分に固まっていないこともあります。(その結果、他のコミュニティのメンバーが興味を持ち、助けを求めているのを見つけることができませんでした)。 Quarkiverse との出会い! Quarkiverse は、提供する GitHub の別組織( https://github.com/quarkiverse )です。 Maven Central への Maven リリースの自動化された安全な公開 Quarkus のビルド/リリースを使用して、拡張機能のクロステストを自動化しました( https://github.com/quarkusio/quarkus-ecosystem-ci を参照)。 拡張機能(code.quarkus.io、コマンドライン、IDEツールなど)を参照するためにQuarkusツールで使用されるレジストリに含まれています。 プロジェクトの一貫したフォーマットとリリース より大きなコミュニティにまさる素晴らしい協力の場 もしあなたが拡張機能の開発をリードしたいのであれば、それがまだ GitHubで提案されていないか確認 したり、または 拡張機能提案の課題を作成 を参照してください。 ブログの記事が作業中です。そこで詳細をお伝えしましょう。とりあえず、 既にある拡張機能 をチェックしてみてください。 ADOPTERS.md Quarkusの使用に関する情報を共有するために、リポジトリのルートに ADOPTERS.mdファイル を追加しました。 Quarkusを使用していて、私たちのブログでインタビューを受けたい場合、または単にこのファイルに追加したい場合は、私たちにご連絡ください。 貢献者 Quarkusには現在 378人の貢献者 がいます。皆様、本当にありがとうございました。 特に1.9リリースについてはみなさんのおかげです。 Abel Salgado Romero, Adam Bien, Alex Soto, Alexey Loubyansky, AlexeyAnufriev, Andrea Cosentino, Andy Damevin, Anh Le (Andy), Armel Soro, Arne Mejlholm, asodja, Auri Munoz, Bill Burke, Bobby Philip, Centro de Computos, Chris Laprun, Clement Escoffier, Daniel Badawi, Daniel Platz, David M. Lloyd, Dillon Fearns, Dmitry Shohov, Driss Amri, Dušan Križan, Emanuel Alves, Enercido Alcantara, Erin Schnabel, Fabian Stäber, Fabio Iwakoshi, Falko Modler, Foivos Zakkak, Galder Zamarreño, Garima Monga, Gautier de Saint Martin Lacaze, Geoffrey De Smet, George Gastaldi, Georgios Andrianakis, ghokun, Guillaume Le Floch, Guillaume Smet, Gunnar Morling, Gytis Trikleris, Harsh Madhani, Harsha R, Ioannis Canellos, Jack Hu, Jaikiran Pai, Jakub Scholz, Jan Martiška, João Lucas Scharf, Julien Ponge, Justin Lee, kdnakt, Ken Finnigan, Kevin Viet, Knut Wannheden, Ladislav Thon, Laurent Broudoux, lburgazzoli, Loïc Mathieu, Maciej Swiderski, Manyanda Chitimbo, Marcin Czeczko, Markus Heberling, Martin Kouba, Matej Vasek, Max Rydahl Andersen, Michal Krzywanski Michał Górniewski, Michał Szynkiewicz, Miguel Serra, Nathan Erwin, Oliver Libutzki, Paul Kunysch, Pedro Igor, Peter Palaga, Phillip Krüger, Roberto Cortez, Rohan Maity, Ron Sigal, Rostislav Svoboda, Sanne Grinovero, Sergey Beryozkin, Simon Bengtsson, Stephane Epardaud, Stuart Douglas, Thomas Pfaff, Vincent Sevel, Vincent Sourin, Vinícius Ferraz Campos Florentino, William Burns, xstefank, Xumk and Yoann Rodière 参加しよう 私たちはあなたのフィードバックをとても大切にしていますので、バグを報告し、改善を依頼してください...一緒に何か素晴らしいものを作りましょう! Quarkusのユーザーや好奇心の強い人は、恥ずかしがらずに歓迎コミュニティに参加してください。 GitHub にフィードバックを提供する; コードを作成して PRを行う ; Zulip や メーリングリスト で議論する; なにか質問があれば Stack Overflow で投稿してください。
(注) 本記事は2020年11月時点の情報です。OpenShift Kubernetes Engineの最新情報については、参考情報として記載しておりますOpenShiftドキュメントも合わせてご参照ください。 Red Hat ソリューションアーキテクトの小島です。 Red Hatが提供しているOpenShift Kubernetes Engineの特徴についてご紹介します。 OpenShift Kubernetes Engine (OKE) とは何か OpenShift Kubernetes Engine (OKE) の対象ユーザ OpenShift Container Platform (OCP) への移行を考える場合 参考情報 OpenShift Kubernetes Engine (OKE) とは何か OpenShift Container Platform (OCP)のサポート範囲を、Red Hatが限定して提供しているOpenShiftとなります。 現時点では(将来的には変更するかもしれませんが)、 OKEとOCPは全く同じソフトウェア構成から成り立っており、OKE専用のソフトウェアを提供するようなことは行っていません。そのため、OKEのユーザはOCPの製品ドキュメント(インストールや設定ガイドなど)をそのまま参照できますし、OCPのソフトウェアアップデートをすべて利用できるようになっています。OKEの ライフサイクルポリシー もOCPと同じであり、OKEのプレミアムサブスクリプションにはOpenShiftの 延長サポートオプション(特定のマイナーリリースに限定) が付属します。なお、OCPでのみ提供する機能の概要は次のとおりです。 OpenShiftクラスターのログ集積 OpenShiftが標準で搭載している、 ElasticSearch, Fluentd, Kibanaベースのロギング Prometheusによる ユーザワークロードのモニタリング Red HatがSaaSとして提供している Metering and cost management 下記のようなアプリケーションの開発/モダナイゼーション/DX推進を支援する機能群 アプリケーションビルド, パイプライン, Developer Console/Catalog, Serverless, Service Mesh, CodeReady Workspacesなど これらの機能についてRed Hatのテクニカルサポートやコンサルティングサービスを受けたい場合は、OKEでなくOCPのサブスクリプションをご購入いただく必要がありますのでご注意ください。OKEのサブスクリプションしか持っていない場合、OCPでのみ提供する機能の利用については、Red Hatのサポートチームによる問い合わせ対応をお断りしています。なお、OCPではなくOKEを購入した場合でも、次のような機能の利用はサポートされます。 OCPのインストーラを利用したインストール Over the Airアップデート/アップグレード SDN/Storageプラグインの利用 OVS/OVN SDNの利用 OpenShift Container Storage (別売り)の利用 Prometheusによるクラスターのモニタリング 外部のコンテナレジストリにあるイメージのインポート及びデプロイ 例えば、Red HatのMiddlewareサブスクリプションをOKEとは別に購入している場合、 Red Hat Ecosystem Catalog などからMiddlewareのイメージをOKE上にインポートしてデプロイ・利用できます。 *1 OpenShiftに同梱されたOperatorHubを利用したアプリケーションデプロイ Red Hat Marketplace を利用したアプリケーションデプロイ OKEのユーザは、OCPのエコシステムによって提供されるコンテナ製品を、OCPと同様に利用できます。 Windows Container 現時点ではOCPでもGAになっていませんので、OCPでのGA以降にOKEでもサポートされる予定です。 OpenShift Virtualization こうしたインフラ関連の機能はOKEでもサポートされますので、OKEのユーザはRed Hat認定のKubernetes環境を構築・運用できるようになっています。ただし、OKEとOCPでは提供する機能やサポート範囲が異なるため、OKEとOCPのクラスターは分離して構築・運用することになります。 OpenShift Kubernetes Engine (OKE) の対象ユーザ OKEは下記のようなユーザを想定しています。 セキュアなKubernetes環境を構築したい OSとKubernetesなどのインテグレーションテストが実施済み エコシステムが作られており、サードパーティが認定しているコンテナアプリケーションの種類が豊富 OKEを利用していても、DX推進などを支援するOCPの機能を利用したい場合は、OCPへの移行を推奨しています。 OpenShift Container Platform (OCP) への移行を考える場合 前述したとおり、現時点ではOKEとOCPは同じソフトウェアを利用しており、OCPのインフラ関連の機能はOKEでも利用できますので、OKEの環境をそのまま活用できます。また、サブスクリプションについては、OKEからOCPのサブスクリプションにアップグレードするための購入・事務手続きを行います。この手続きの詳細については、Red Hatの営業までお問い合わせください。 参考情報 OKEについての最新情報は下記もご参照ください。OKEの紹介ドキュメントや、OKEでサポートされる機能一覧を掲載しています。 docs.openshift.com access.redhat.com *1 : Red HatはOpenShiftがバンドルされたMiddlewareのサブスクリプションを提供していますが、この場合、バンドルされたOpenShiftはOCPのみの扱いとなります。OKEがバンドルされたMiddlewareのサブスクリプションについては、現時点では提供していません。
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 Quarkus 1.8.3.Final released - Bugfixes の翻訳記事です。 本日、Quarkus 1.8.3.Final をリリースしました。このリリースには、厄介なリグレッションの修正やその他の修正が含まれています。 これは、Quarkus 1.8を使用しているすべての人にとって安全なアップグレードです。 何が新しいの? このリリースは 1.8.2.Final で見つかった様々なバグの修正とドキュメントの更新を行うメンテナンスリリースです。 主な変更点は、 slf4j-jboss-logging のリグレッションによる slf4j-jboss-logging のダウングレードです: https://github.com/quarkusio/quarkus/issues/12615 . GitHub で 1.8.3.Final の完全な変更履歴 を入手できます。 参加しよう 私たちはあなたのフィードバックをとても大切にしていますので、バグを報告し、改善を依頼してください...一緒に何か素晴らしいものを作りましょう! Quarkusのユーザーや好奇心の強い人は、恥ずかしがらずに歓迎コミュニティに参加してください。 GitHub にフィードバックを提供する; コードを作成して PRを行う ; Zulip や メーリングリスト で議論する; なにか質問があれば Stack Overflow で投稿してください。
Red Hat で Solution Architect として Quarkus を担当している伊藤ちひろ( @chiroito )です。 この記事は、Quarkus.io のブログ記事、 From zero to hero on backporting pull requests の翻訳記事です。 Quarkus プロジェクトの動きは速いです。バグフィックスリリースを準備するときには、通常、バックポートするためのプルリクエストが数十件発生します。バックポートするためのプルリクエストの数は膨大です。GitHub の UI を使って行うのは不便ですし、時間もかかります (PR をクリックし、コミットハッシュを入念に選択してコピー/貼り付けて、ラベルを削除し、マイルストーンを割り当て、すべての修正済みの課題にマイルストーンを割り当て、次へ)。また、UI にはいくつかの制限があります。そこで、この作業を自動化することにして、アプリケーションを構築しました。もちろん、Quarkus と一緒です! 解決策を掘り下げる前に、リリースのプロセスを簡単に説明します。 リリースプロセス Quarkus チームは、 メジャー.マイナー.パッチ.分類子 (例:1.7.0.CR1、1.7.0.Final)のバージョンパターンを採用しています。上がったバージョンによって、異なるプロセスが採用されています。 メジャーとマイナーのリリース 私たちのマスターブランチは、次のメジャー、マイナーリリースに向けて常に準備ができています。このプロセスは通常、非常にスムーズで、バックポートを伴いません。 パッチや分類子のリリース Quarkus で新しいパッチが適用されたバージョン(または2つ目のCR)がリリースされるたびに、リリースチームはマスターブランチにマージされたプルリクエストからのコミットをバックポートし始めます。彼らはどうやってどのプルリクエストを得るのかを知っているのでしょうか?私たちは トリアージ/バックポート のラベルがあります?このラベルは今後のパッチリリースで使用する価値のある機能のリクエストを引き出すためにチームが追加するものです。 どうやって自動化するの? このアプリケーションは基本的に、GitHub リポジトリのマージされたプルリクエストと、特定のラベルを含むクローズ済みの課題を照会します( GitHubが公開しているGraphQL APIを 使用)。そして、それらのマイルストーンを UI で選択したものに変更します(その後、特定のラベルを削除します)。これらのプルリクエスト (別名:チェリーピック) でもたらされた変更を適用することは、各プルリクエストの隣にボタンを用意して、必要な git cherry-pick コマンドをクリップボードにコピーすることで簡単になりました。このステップは、リリースエンジニアが手動で行うことを推奨します。 スクリーンショット マイルストーンの選択 バックポートするプルリクエストの選択 Quarkusの実績 ここでは、バックポートアプリケーションで使用されている拡張機能の概要を紹介しています。 ArC (CDI):サービスのライフサイクルを管理 MicroProfile Config:プロパティを外部化 RESTEasy:UI が消費できるエンドポイントを公開また、Qute のType-safe テンプレートを使ったUIも提供(Qute参照) Qute:すべてのテンプレート(UI および GraphQL クエリ ペイロード)で使用 Rest Client:GitHub の GraphQL エンドポイントを呼び出す Cache:GitHub の GraphQL エンドポイントから開いているマイルストーンをキャッシュ Hibernate Validator:入力の有効性を確認 Jackson (JSON ライブラリ):GitHub GraphQL エンドポイントから結果をパース ライブコーディング ライブコーディングは Quarkus の素晴らしい機能で、開発中にクラスやメソッドが変更されている間に素早くフィードバックを提供してくれました。経験則として、Quarkus アプリケーションの開発中は常に ./mvnw quarkus:dev を使用してください。 MicroProfile Config どの GitHub リポジトリを使うか (テストを使うか、Quarkus 以外のリポジトリを使うか) と GitHub 認証トークン (必要に応じて別のバックポートラベルも) を設定すれば、ソースコードを変更することなく簡単に設定できるはずです。Quarkus は Microprofile Config を使用しているので、これらのプロパティを外部化しました。Quarkus は .env ファイルもサポートしており、テスト中に使用しました。これにより、アプリケーションを実行する前に application.properties を直接変更したり、環境やシステムのプロパティを設定したりする必要がないため、ローカルテストが簡単になりました。 Qute Qute はテンプレートエンジンです。UI を生成したり、GraphQL 変数を使うだけでは不十分な場合に GraphQL クエリを生成するために使用しました。例えば、 課題番号のリストから課題データを取得します 。 型安全のテンプレートを 使って UI と GraphQL クエリを生成しました。 Rest Client GraphQL とは、簡単に言えば、JSON データを HTTP エンドポイントに POST し、その結果を JSON ドキュメントとして解析することを意味します。単純にそれだけです。Microprofile REST Client は、このタスクを実行するのに適しているということで、こんなことを思いつきました。 import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.core.HttpHeaders; import io.vertx.core.json.JsonObject; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @RegisterRestClient(baseUri = "https://api.github.com/graphql" ) public interface GraphQLClient { @POST JsonObject graphql( @HeaderParam(HttpHeaders.AUTHORIZATION) String authentication, JsonObject query); } GitHubService で GraphQLClient オブジェクトを使えるようになりました。 @Inject @RestClient GraphQLClient graphQLClient; クライアントがどのように起動されるかは、 ここで 見ることができます。 次のステップ 動的クエリの性質を考えると、SmallRye GraphQL 拡張機能は使わないことにしました。ですが、拡張機能がその機能をサポートするようになれば、変更できます。 感謝 このアプリケーションは開発に約 1 週間かかりました(GraphQLの学習も含まれています)。それが可能になったのは、以下の Quarkus チームのメンバーのおかげです。 Guillaume Smet 氏:美しいフロントエンドの仕事 George Gastaldi 氏:バックエンドの開発と GraphQL の統合を楽しむ David Lloyd 氏:コミットメッセージで課題番号を抽出するために必要なクレイジーな正規表現 詳細情報 Quarkus Backports のソース: https://github.com/quarkusio/quarkus-backports Quarkus のウェブサイト: https://quarkus.io Quarkus GitHub プロジェクト: https://github.com/quarkusio/quarkus Quarkus Twitter: https://twitter.com/QuarkusIO Quarkus のチャット: https://quarkusio.zulipchat.com/ Quarkus のメーリングリスト: https://groups.google.com/forum/#!forum/quarkus-dev Quarkus を使う 4 つの理由
Red Hatでソリューションアーキテクトをしている杉本です。 この記事は Red Hat Developer Blog の APIs as a Product: Get the value out of your APIs を許可をうけて翻訳したものです。 ProgrammableWeb が発表したこの2019年のレポートに見られるように、APIの普及は続いており、昨年の成長率は30%増となっています。企業をよりオープンなものとし、イノベーションを促進するために、APIはますます必要となっています。 Payment Services Directive version 2(PSD2) 、 オープンバンキング 、オープンデータAPIを公開する公共機関などはその一例です。このようにAPIが豊富にある中で、APIから価値を引き出し、競争が激化する中で差別化を図ることがますます重要になってきています。今やAPIは「プロダクト(製品)」として設計・管理すべきなのです。 組織を変える APIをプロダクトとして設計するということは、APIの設計と管理の方法を大きく変えることを意味します。つまり「既存のサービスをパッケージ化する」という考え方から「顧客のニーズを満たす」という考え方に変える必要があります。この考え方では、APIを担当するチームはAPIというプロダクト(製品)を担当することになり、したがって、 既存のアセット(資産)ではなく、顧客のニーズに焦点を当て、 プロジェクトの期間だけではなく、継続的にAPIを管理し、 有限のリソースから弾力性のあるコンピューティングへと移行し、 APIに特化した中央集権的なチームから、さまざまな能力を持つクロスファンクショナルな製品チームへと進化する、 ことになります。 要するに、APIをプロダクト(製品)として設計するということは次のことを意味します: 顧客の問題を解決するものとしてAPIを捉えるということ APIによって提供される価値の共有指標を設定すること 何を改善すべきかを知るためのフィードバックループを持つこと 設計プロセスを変える APIファーストのアプローチ APIをプロダクト(製品)としてデザインするということは、APIの作り方を変えるということでもあります( デザイン思考 の考え方を適用します)。 APIに適用されたデザイン思考の最初のステップは、顧客にフォーカスすることです。顧客の目を通して見た場合に、顧客にとっての痛みは何か?  共感する ということは潜在的な新規顧客と会って話を聞くことを意味します。そうすることにより、顧客が理解していること、顧客の組織構造、顧客が利用しているエコシステムの技術要素などを発見することができるでしょう。 次に、そこで見出されたことを総合して、顧客が解決しようとしている 問題が何かを定義 し、 Job to be Done(解決したい課題) を特定します。例えばペットを購入するために支払い処理をしたい顧客と、自分が所有するペットの数を計算しようとしている顧客とでは、まったく異なるPetstore APIが必要となるでしょう。 問題が一旦定義されたら、 APIのアイデア創造というプロセスを通して新しいアイデアを育てる ことができます。このステップでは、そのアイデアがソリューションとして適切であるかどうかを確認するために、APIを異なる設計で作ってみたりします。 APIプロトタイピング の段階では、 意味のある例に基づいてAPIのモックを作成 し、実際に動作するAPIを作ります。他のチームメンバーはAPI設計案に関してフィードバックを行うことができます。 最後の前段階のステップでは、アーリーアダプターから最終的なデザインについての フィードバックを得る ことで、APIに対するビジネス的な期待値を調整します。 最終的に、実際のAPIを 実装 していきます。 APIプロダクトの設計を支援するオープンソースコミュニティ ここまでは組織の変更についての話でしたが、専用のツールとオープンソースのコミュニティを活用することで、APIプロダクトの設計と管理をよりうまく行うことが可能です。 Microcks はオープンソースのKubernetesネイティブのツールで、 アイデア創造 のフェーズと プロトタイピング のフェーズにおいてAPIのモック作成とテストを行うことができます。 Apicurio は、より良いAPIコントラクト(契約)を共同で設計するのに役立ちます。アーキテクト、プロダクトオーナー、デザイナー、開発者が共同でAPI設計を行うことができます。 Red Hat 3scale API Management は、APIの設計プロセスを円滑にし、フィードバックを収集してAPIをプロダクトとして管理することにより、APIプロダクトの設計・管理を容易にします。 次回は、3scaleが実際にどのようにAPIをプロダクトとして構築するのに役立つのかを見ていきます。 上記は英語記事の翻訳ですが、 Red Hat Developer Channelのウェビナー においてカスタマージャーニーにおけるAPIの役割とカスタマーエンゲージメントのハブとなるレッドハット製品について日本語で解説しておりますのでぜひご視聴頂ければ幸いです。
みなさんこんにちは。レッドハットの杉村です。Ansible のテクニカルサポートをしています。 Ansible Engine や Ansible Tower は Python で書かれています。今回の記事では、Python の実行環境についてお話したいと思います。 Python は 2.7 と 3 で互換性がありません。この違いがよく問題となります。 RHEL に標準搭載されている Python RHEL 7 では Python 2.7.5 が標準搭載されていますが、RHEL 8 にはありません。/usr/libexec/platform-python として 3.6.8 がインストールされているものの、これは OS の管理に使うことが想定されているものです。 RHEL 7 で利用できる Python RHEL 7 では標準搭載されている 2.7.5 以外にも、RHSCL (Red Hat Software Collections) で利用できる Python や、RHEL 7.7 以降で含まれるようになった Python をインストールして使うことができます。RHSCL のリポジトリは、RHEL のサブスクリプションをお持ちであれば一部の例外を除いてご利用いただけます。 リポジトリ 利用できるPython パッケージ名 rhel-7-server-rpms 2.7.5 python rhel-7-server-rpms 3.6.8 python3 (RHEL 7.7以降) rhel-server-rhscl-7-rpms 2.7.17 python27-python rhel-server-rhscl-7-rpms 3.4.2 rh-python34-python rhel-server-rhscl-7-rpms 3.5.1 rh-python35-python rhel-server-rhscl-7-rpms 3.6.12 rh-python36-python rhel-server-rhscl-7-rpms 3.8.6 rh-python38-python 例えば Python 3.8 を使うには、RHSCL のリポジトリを有効にしてインストールできます。 # subscription-manager repos --enable=rhel-server-rhscl-7-rpms リポジトリー 'rhel-server-rhscl-7-rpms' は、このシステムに対して有効になりました。 # yum install rh-python38 … インストール: rh-python38.x86_64 0:2.0-4.el7 依存性関連をインストールしました: libtirpc.x86_64 0:0.2.4-0.16.el7 rh-python38-python.x86_64 0:3.8.6-1.el7 rh-python38-python-libs.x86_64 0:3.8.6-1.el7 rh-python38-python-pip.noarch 0:19.3.1-1.el7 rh-python38-python-pip-wheel.noarch 0:19.3.1-1.el7 rh-python38-python-setuptools.noarch 0:41.6.0-7.el7 rh-python38-python-setuptools-wheel.noarch 0:41.6.0-7.el7 rh-python38-runtime.x86_64 0:2.0-4.el7 scl-utils.x86_64 0:20130529-19.el7 完了しました! # scl --list rh-python38 # scl enable rh-python38 /bin/bash # python -V Python 3.8.6 # exit exit RHSCL でインストールされたものを利用するためには、scl enable コマンドでその環境を構成する必要があることに注意してください。詳しくはこちらのドキュメントもご参照ください。 access.redhat.com RHEL 8 で利用できる Python RHEL 8 では、必要な Python をインストールして使います。 リポジトリ 利用できるPython パッケージ名 rhel-8-for-x86_64-baseos-rpms 3.6.8 platform-python rhel-8-for-x86_64-appstream-rpms 2.7.17 python2 rhel-8-for-x86_64-appstream-rpms 3.6.8 python36 rhel-8-for-x86_64-appstream-rpms 3.8.0 python38 AppStream から提供されているものはライフサイクルに注意が必要です。 Pythonのバージョン ライフサイクル 3.6 RHEL 8 と同じ 2.7 2024年6月まで 3.8 2023年5月まで 詳しくはこちらのドキュメントをご確認ください。 access.redhat.com access.redhat.com access.redhat.com Ansible Engine が使う Python Red Hat が提供する Ansible Engine は、それぞれこれらのリポジトリから利用できます。 RHEL リポジトリ RHEL 7 rhel-7-server-ansible-2-rpms RHEL 8 ansible-2-for-rhel-8-x86_64-rpms 2020年10月30日現在の最新版である 2.9.14 では、それぞれこのような依存関係となっています。追加で Python の実行環境をインストールしなくても利用できることがわかります。 RHEL 7 # yum deplist ansible-2.9.14 読み込んだプラグイン:product-id, search-disabled-repos, subscription-manager パッケージ : ansible.noarch 2.9.14-1.el7ae 依存性 : /usr/bin/python2 provider: python.x86_64 2.7.5-89.el7 依存性 : PyYAML provider: PyYAML.x86_64 3.10-11.el7 依存性 : python(abi) = 2.7 provider: python.x86_64 2.7.5-89.el7 依存性 : python-jinja2 provider: python-jinja2.noarch 2.7.2-4.el7 依存性 : python-paramiko provider: python-paramiko.noarch 2.1.1-9.el7 依存性 : python-six provider: python-six.noarch 1.9.0-2.el7 依存性 : python2-cryptography provider: python2-cryptography.x86_64 1.7.2-2.el7 依存性 : sshpass provider: sshpass.x86_64 1.06-2.el7 RHEL 8 # dnf deplist ansible-2.9.14 Updating Subscription Management repositories. メタデータの期限切れの最終確認: 0:06:45 時間前の 2020年10月30日 14時16分47秒 に実施しました。 package: ansible-2.9.14-1.el8ae.noarch dependency: /usr/libexec/platform-python provider: platform-python-3.6.8-23.el8.i686 provider: platform-python-3.6.8-23.el8.x86_64 dependency: python(abi) = 3.6 provider: platform-python-3.6.8-23.el8.i686 provider: platform-python-3.6.8-23.el8.x86_64 dependency: python3-PyYAML provider: python3-pyyaml-3.12-12.el8.x86_64 dependency: python3-cryptography provider: python3-cryptography-2.3-3.el8.x86_64 dependency: python3-jinja2 provider: python3-jinja2-2.10.1-2.el8_0.noarch dependency: python3-six provider: python3-six-1.11.0-8.el8.noarch dependency: sshpass provider: sshpass-1.06-3.el8ae.x86_64 provider: sshpass-1.06-3.el8ae.x86_64 Ansible Tower が使う Python Ansible Tower は Web UI やバックグラウンドプロセスを動作させるために Python の実行環境を利用します。 Ansible Tower 3.5 からは Python 3 を利用して動作するようになりました。RHEL 7 では標準で搭載されていないため、バージョンによって複雑な事情が生じてしまっています。 RHEL Towerのバージョン Pythonの実行環境 RHEL 7.4〜7.6 3.5, 3.6 rh-python36 RHEL 7.4〜7.6 3.7 Tower はインストールできない RHEL 7.7〜 3.5, 3.6 rh-python36 RHEL 7.7〜 3.7 python3 RHEL 8 3.5, 3.6, 3.7 python36 最新版の Ansible Tower 3.7 では RHEL 7.7 以降で利用できるようになった python3 を利用するようになったため、RHEL 7.6 以前の OS のバージョンでは動作しなくなりました。 Ansible Tower から呼び出される Ansible Engine が使う Python Ansible Tower をインストールしますと2つの virtual environment が作成されます。 venvのパス 用途 /var/lib/awx/venv/ansible/ Ansible Engine 実行環境 /var/lib/awx/venv/awx/ Web UI やバックグラウンドプロセスの実行環境 Ansible Tower からジョブテンプレートを実行しますと、この Ansible Engine 実行環境を使って ansible-playbook コマンドを実行します。この venv では RHEL にインストールされている Ansible Engine を参照しつつ、追加で必要なモジュールが利用できるものとなっています。例えば Windows サーバへの接続に必要な pywinrm などが使えるようになっており、このように確認することができます。 # su - awx $ source /var/lib/awx/venv/ansible/bin/activate (ansible) $ pip freeze -l ... (ansible) $ deactivate $ この venv は目的に応じて追加で作成して Tower から利用することもできます。同じチームの八木澤(ひよこ大佐)が以前書いた記事に詳しく説明されていますのでご覧ください。 rheb.hatenablog.com RHEL 7 でも Python 3 の Ansible を利用したいというときには、例えばこのように作成することができます。RHEL 7.9 + Ansible Tower 3.7.3 で実行してみました。python3-devel パッケージが必要なことから、rhel-7-server-optional-rpms を有効にしています。 # subscription-manager repos --enable rhel-7-server-optional-rpms # yum install gcc python3-devel openssl-devel # python3 -m venv /var/lib/awx/venv/mypy3 # source /var/lib/awx/venv/mypy3/bin/activate (mypy3) # umask 0022 (mypy3) # pip3 install python-memcached psutil ansible==2.9.14 (mypy3) # deactivate pip3 コマンドから ansible をインストールしようとしますと、バージョンを指定しないときは 2.10 を入れようとします。2.10 はこの記事の執筆時点(2020年10月30日)ではサポートしていませんのでご注意ください。 いまの手順では pip3 コマンドから必要最低限のモジュールのみをインストールしましたが、追加で必要とするモジュールを利用したいということがありましたら、deactivate して抜ける前にインストールしてください。 この venv を使ってジョブテンプレートを実行してみます。Ansible Tower の Web UI から参照できるようにするためには、一度ログアウトしてログインし直す必要があります。ジョブテンプレートの画面で、 ANSIBLE ENVIRONMENT からプルダウンで出てくるので選択します。 このジョブテンプレートを実行しますと、先ほど作成した venv (mypy3) を利用して実行されていることがわかります。 Ansible でよく起こる実行環境の問題 venv を作らずに RHEL のシステムワイドの Python 実行環境に pip コマンドで Ansible をインストールして、実行した際にトラブルになるという事例がよくあります。 一番問い合わせを受けるエラーはこちらのものです。Python 2.7 と 3 が混在している場合に発生します。venv できちんと切り分けて実行環境を管理することで解消します。 AttributeError: module 'enum' has no attribute 'IntFlag' おわりに Python の開発元での Python 2.7 のサポートが終了したことから、Python 3 に早く移行したいというお問い合わせもよくいただきます。 www.python.org RHEL でのサポートについてはこちらにまとまっておりますのでご参照ください。開発元でのサポート終了に関わらず、RHEL としてはそのライフサイクルに従ってサポートが提供されます。 access.redhat.com 全ての場面で完全に Python 2.7 を捨てるには、RHEL 8 への移行をお勧めします。 Ansible Towerの評価ライセンスリクエストはこちらからご利用いただけますのでお試しください。 www.ansible.com Happy Automation!