はじめまして、Red Hatの西村と申します。4月に入社して以来、初めての投稿です。よろしくお願いいたします。
この記事はRed Hat DeveloperのAutomate workshop setup with Ansible playbooks and CodeReady Workspacesを、許可を受けて翻訳したものです。
:::James Falkner 2020年7月3日:::
Red Hatでは、お客様やパートナー、その他のオープンソース開発者を対象に、多くの対面および仮想ワークショップを行っています。ほとんどの場合、ワークショップは「自身のデバイスを持ち込む」ものなので、さまざまなハードウェアおよびソフトウェアのセットアップ、企業のエンドポイント保護スキーム、システム知識のレベルの違いといった問題に直面します。
ここ数年、私たちはRed Hat CodeReady Workspaces (CRW)を多用してきました。Eclipse CheをベースにしたCodeReady Workspacesは、ほとんどの開発者に馴染みのあるブラウザで動作するIDEで、プリインストールやシステム内部の知識は必要ありません。ブラウザと頭脳だけあれば、ハンズオンを行うことができます。
また、Quarkusのワークショップを自動化するために、Red Hat Ansible用のプレイブックのセットを作成しました。プレイブックは便利ですが、Kubernetes上でのQuarkus開発用のCodeReady Workspacesの大規模なデプロイを自動化するのに特に役立ちます。この記事ではプレイブックを紹介し、独自の自動化を行う際にそれらを使用する方法を示します。
大規模な自動化の概要
Quarkusのワークショップを自動化するために、私たちはCodeReady Workspacesとこの記事で紹介するAnsibleプレイブックを使用していますが、多くの企業では大規模な新規開発者のオンボーディングを自動化するためにCodeReady Workspacesを使用しています。その場合、CodeReady Workspacesを使用することで、企業の知的財産(つまりソースコード)を保護し、「自分のマシン上では上手くいく」というバグに対する言い訳を最小限に抑えることができます。
ワークショップを実施しているかオンボーディングプロセスを実施しているかに関わらず、可能な限りスムーズに行うためには、かなりのセットアップが必要になります。ワークショップの場合、Red Hat OpenShiftをデプロイし、予想されるユーザー数に合わせてスケールし、すべてのユーザーにCodeReady Workspacesをインストールして設定する必要があります。また、最高の体験を得るためには、各ワークスペースを「事前ウォームアップ」して、イントロのスライドが終わる頃にはすでに実行されているようにするべきです。また、ワークショップの一部として使用するオペレーターをインストールする必要もあります。
次のセクションでは、それぞれの手順と、それらを自動化するために作成したAnsibleプレイブックについて説明します。セットアップのほとんどは、会社のポリシーとITポリシーの両方に準拠し、さらに開発者のニーズにも対応したカスタムスタックの作成に応用できます。
OpenShiftのインストール
OpenShiftはハイブリッドクラウドインフラストラクチャに使用されるため、大規模なデプロイでは、zipファイルをダウンロードして解凍し、デスクトップ上で実行するという古典的な意味での「インストール」は行いません。CodeReady Containersを使用してそのようなタイプのインストールを行うこともできますが、ワークショップで何十人あるいは何百人もの開発者をサポートしている場合、ローカルで実行することは選択肢ではありません。
OpenShiftは、複数の異なるパブリッククラウドとプライベートクラウド上で、簡単にプロビジョニングできます。OpenShiftのデプロイはこの記事の対象外ですが、受講者5人ごとに追加のOpenShiftワーカーノードをデプロイし、各ノードに64GiBのメモリを割り当てるのが有用であるとわかりました。このセットアップにより、すべての受講者が快適なワークショップ体験を受けることができます。
Quarkusワークショップでは、受講者にQuarkusのネイティブビルドを実施してもらいますが、これには余分なメモリを必要です。また、各受講者は独自のKafkaクラスタや他のいくつかのアイテムをデプロイします。そのためワークショップを一度実行して、すべてを実行中にしておき、その上ですべてを足し合わせて、ユーザーごとに必要なメモリの量を決定します。CodeReady Workspacesでは、「ワークスペース単位」の永続ボリューム要求(PVC)戦略を使用することに注意してください。各ワークスペース(つまり各ユーザー)が、独自のストレージを取得します。この戦略に従うことを選択した場合、十分なストレージの容量を確保する必要があります。CPUは多ければ多いほど良いでしょう。
OpenShiftをインストールしたら、ユーザーを作成する必要があります。基本的なLinuxシェルスクリプトやoc
コマンドを使用して、デフォルトのOpenShiftの認証メカニズムを上書きし、ユーザー(adminユーザーを含む)を包含するhtpasswd
ファイルを供給することができます。このBashスクリプトには、htpasswd
ユーティリティとyq
ユーティリティ(バージョン3以上)も必要です。
#!/bin/bash NUMUSERS=20 TMPHTPASS=$(mktemp) for i in {1..$NUMUSERS} ; do htpasswd -b ${TMPHTPASS} "user$i" 'somepassword' done htpasswd -b ${TMPHTPASS} admin 'adminpassword' $ oc -n openshift-config delete secret workshop-user-secret $ oc -n openshift-config create secret generic workshop-user-secret --from-file=htpasswd=${TMPHTPASS} $ oc -n openshift-config get oauth cluster -o yaml | \ yq d - spec.identityProviders | \ yq w - -s htpass-template.yaml | \ oc apply -f - sleep 20 # don't shoot the messenger, Operators are "eventually consistent" $ oc adm policy add-cluster-role-to-user cluster-admin admin
yq
(バージョン3)で使用するhtpass-template.yaml
テンプレートは以下のようになります。
spec.identityProviders[+]: name: htpassidp type: HTPasswd mappingMethod: claim htpasswd: fileData: name: workshop-user-secret
このテンプレートでスクリプトを実行すると、新しいIDプロバイダがOpenShiftの認証フローにマージされ、ユーザーがログインできるようになります。Ansibleを使ってこの認証プロセスを設定することもできますが、まだそれを実施する時間を見つけられていません。
CodeReady Workspacesのデプロイ
今回のインストールにはCodeReady Workspaces Operatorを使用します。インストールを自動化するために、Ansibleプレイブック内でAnsibleを少し使います。名前空間がまだ存在しない場合は、OperatorGroupとSubscriptionに加えて、k8sモジュールを使用して名前空間を作成します。
# create codeready namespace - name: create codeready namespace k8s: state: present kind: Project api_version: project.openshift.io/v1 definition: metadata: name: "codeready" annotations: openshift.io/description: "" openshift.io/display-name: "CodeReady Project" # deploy codeready operator - name: Create operator subscription for CodeReady k8s: state: present merge_type: - strategic-merge - merge definition: "{{ lookup('file', item ) | from_yaml }}" loop: - ./files/codeready_operatorgroup.yaml - ./files/codeready_subscription.yaml # wait for CRD to be a thing - name: Wait for CodeReady CRD to be ready k8s_facts: api_version: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition name: checlusters.org.eclipse.che register: r_codeready_crd retries: 200 delay: 10 until: r_codeready_crd.resources | list | length == 1 # deploy codeready CR - name: Create CR for CodeReady k8s: state: present merge_type: - strategic-merge - merge definition: "{{ lookup('file', item ) | from_yaml }}" loop: - ./files/codeready_cr.yaml # wait for CodeReady to be up - name: wait for CRW to be running uri: url: https://codeready-codeready.{{ route_subdomain }}/dashboard/ validate_certs: false register: result until: result.status == 200 retries: "120" delay: "15"
カスタムリソース定義(CRD)を待っているコードは重要です。CRDがシステムに知られる前にCRDに基づいてカスタムリソース(CR)を作成しようとすると、失敗します。さらに、オペレーターがインストールされると、その知識を得るまでに時間がかかります。
最後に、uriモジュールを使用して、CodeReady Workspaces自体を待ちます。次に、追加の構成を行うためです。
OperatorGroup
OperatorGroupは、codeready_operatorgroup.yaml
に定義されています。非常にシンプルですが、オペレーターが操作できる必要があります。
apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: generateName: codeready- annotations: olm.providedAPIs: CheCluster.v1.org.eclipse.che name: codeready-operator-group namespace: codeready spec: targetNamespaces: - codeready
Subscription
codeready_subscription.yaml
に定義されたSubscriptionも、基本的なものです。
apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: codeready-workspaces namespace: codeready spec: channel: latest installPlanApproval: Automatic name: codeready-workspaces source: redhat-operators sourceNamespace: openshift-marketplace
CheCluster object
OperatorがCRDをKubernetesに登録したら、最後にcodeready_cr.yaml
に定義されたCheCluster
オブジェクトを作成します。CheCluster
を作成することで、インストールが開始されます。
apiVersion: org.eclipse.che/v1 kind: CheCluster metadata: name: codeready-workspaces namespace: codeready spec: server: cheImageTag: '' cheFlavor: codeready devfileRegistryImage: '' pluginRegistryImage: '' tlsSupport: true selfSignedCert: false serverMemoryRequest: '2Gi' serverMemoryLimit: '6Gi' customCheProperties: CHE_LIMITS_WORKSPACE_IDLE_TIMEOUT: "0" database: externalDb: false chePostgresHostName: '' chePostgresPort: '' chePostgresUser: '' chePostgresPassword: '' chePostgresDb: '' auth: openShiftoAuth: false identityProviderImage: '' externalIdentityProvider: false identityProviderURL: '' identityProviderRealm: '' identityProviderClientId: '' storage: pvcStrategy: per-workspace pvcClaimSize: 1Gi preCreateSubPaths: true
メモリ制限に注意してください。これは、私たちのCodeReady Workspacesのカスタムスタックのコンテナ用にチューニングされています。また、ここでは CHE_LIMITS_WORKSPACE_IDLE_TIMEOUT
も設定しています。しばらく席を離れてラボがタイムアウトし、戻ってきたときには更新(または再ログイン)が必要なのは、かなり面倒です。もちろんこれらの設定は、どちらも本番環境では使用すべきではありません。
Keycloakのチューニング
OpenShiftの組み込みの認証メカニズムを使用して、ワークスペースを事前に作成し、起動しておくことはできません。そのためには、各ユーザーが OpenShift にログインし、ユーザーのアカウント詳細をRed Hat Single Sign-Onにリンクする必要があります。(ちなみに、CheClusterリソースでopenShiftoAuth: false
となっているのはこのためです。)
この問題の回避策は、以下のようにCodeReady Workspacesで再びAnsibleを使用して、同じユーザーセットを作成することです。
- name: create codeready users include_tasks: add_che_user.yaml vars: user: "{{ item }}" with_list: "{{ users }}"
この例では、users
はAnsibleのユーザ名の配列にすぎません(例えば、[user1, user2, ....]
)。ループ処理をして、add_che_user.yaml
にユーザーを追加します。以下のように、CodeReady Workspaces REST APIを使用してSSO管理者ユーザーの資格情報を取得し、ユーザーを作成します。
- name: Get codeready SSO admin token uri: url: https://keycloak-codeready.{{ route_subdomain }}/auth/realms/master/protocol/openid-connect/token validate_certs: false method: POST body: username: "{{ codeready_sso_admin_username }}" password: "{{ codeready_sso_admin_password }}" grant_type: "password" client_id: "admin-cli" body_format: form-urlencoded status_code: 200,201,204 register: codeready_sso_admin_token - name: Add user {{ user }} to Che uri: url: https://keycloak-codeready.{{ route_subdomain }}/auth/admin/realms/codeready/users validate_certs: false method: POST headers: Content-Type: application/json Authorization: "Bearer {{ codeready_sso_admin_token.json.access_token }}" body: username: "{{ user }}" enabled: true emailVerified: true firstName: "{{ user }}" lastName: Developer email: "{{ user }}@no-reply.com" credentials: - type: password value: "{{ workshop_che_user_password }}" temporary: false body_format: json status_code: 201,409
このプレイブックには、いくつかの変数があります。
route_subdomain
は、クラスターのデフォルトのOpenShiftサブドメインです(クラスターを検出するには、oc whoami --show-cluster
を使います)。workshop_che_user_password
は、ユーザーが希望するパスワードです。codeready_sso_admin_username/codeready_sso_admin_password
は、CodeReady Workspacesが使用するKeycloakインスタンスの管理者ユーザー名とパスワードです。
デプロイされたKeycloakの環境変数から、Keycloak管理者ユーザー名とパスワードをプログラムで検出するには、Ansibleのコードとk8s_factsモジュール
をもう少し使います。
- name: Get codeready keycloak deployment k8s_facts: kind: Deployment namespace: codeready name: keycloak register: r_keycloak_deployment - name: set codeready username fact set_fact: codeready_sso_admin_username: "{{ r_keycloak_deployment.resources[0].spec.template.spec.containers[0].env | selectattr('name','equalto','SSO_ADMIN_USERNAME') |map (attribute='value') | list | first }}" - name: set codeready password fact set_fact: codeready_sso_admin_password: "{{ r_keycloak_deployment.resources[0].spec.template.spec.containers[0].env | selectattr('name','equalto','SSO_ADMIN_PASSWORD') |map (attribute='value') | list | first }}"
次に、SSOトークンの有効期限とSSOセッションのタイムアウト時間を増やします(これにより、ワークショップ中のイライラするログアウトを避けることができます)。
- name: Increase codeready access token lifespans uri: url: https://keycloak-codeready.{{ route_subdomain }}/auth/admin/realms/codeready validate_certs: false method: PUT headers: Content-Type: application/json Authorization: "Bearer {{ codeready_sso_admin_token.json.access_token }}" body: accessTokenLifespan: 28800 accessTokenLifespanForImplicitFlow: 28800 actionTokenGeneratedByUserLifespan: 28800 ssoSessionIdleTimeout: 28800 ssoSessionMaxLifespan: 28800 body_format: json status_code: 204
ユーザーのワークスペースの事前ウォームアップ
最後に、CRWのワークスペースを事前に作成し、事前ウォームアップしておく準備が整いました。
- name: Pre-create and warm user workspaces include_tasks: create_che_workspace.yaml vars: user: "{{ item }}" with_list: "{{ users }}"
ユーザーのワークスペースを作成するために行ったのと同じようなループ処理を実行します。今回は、CodeReady Workspaces REST APIを使用したcreate_che_workspace.yaml
を呼び出します。
- name: "Get Che {{ user }} token" uri: url: https://keycloak-codeready.{{ route_subdomain }}/auth/realms/codeready/protocol/openid-connect/token validate_certs: false method: POST body: username: "{{ user }}" password: "{{ workshop_che_user_password }}" grant_type: "password" client_id: "admin-cli" body_format: form-urlencoded status_code: 200 register: user_token - name: Create workspace for {{ user }} from devfile uri: url: "https://codeready-codeready.{{ route_subdomain }}/api/workspace/devfile?start-after-create=true&namespace={{ user }}" validate_certs: false method: POST headers: Content-Type: application/json Authorization: "Bearer {{ user_token.json.access_token }}" body: "{{ lookup('template', './templates/devfile.json.j2') }}" body_format: json status_code: 201,409 register: workspace_def
devfileについて
devfile.json.j2
は、CodeReady devfileのAnsible Jinja2 テンプレートです。今回のdevfileの例はこちらで参照できます。興味深いのは、以下の部分です。
"components": [ { "id": "redhat/quarkus-java11/latest", "type": "chePlugin" },
devfileには、ワークスペース用のQuarkusプラグインが含まれていることに注意してください。これにより、オートコンプリートやその他のヒントなどのIDE機能が提供されます。
"image": "image-registry.openshift-image-registry.svc:5000/openshift/quarkus-stack:2.1",
ここでは、事前に生成され、以下の定義を使ってOpenShiftにImageStreamとしてデプロイされたCheのスタックを参照します。
apiVersion: image.openshift.io/v1 kind: ImageStream metadata: name: quarkus-stack namespace: openshift spec: tags: - annotations: description: Quarkus stack for Java and CodeReady Workspaces iconClass: icon-java supports: java tags: builder,java version: "2.1" from: kind: DockerImage name: quay.io/openshiftlabs/quarkus-workshop-stack:2.1 name: "2.1"
スタックは、ユーティリティ(oc
、kn
、tkn
、GraalVM
)を含むDockerfileを使用して構築しました。ユーザーがワークショップを開始するたびにインターネットからダウンロードしないように、イメージにMaven .m2
リポジトリを事前入力するいくつかのテストビルドを実行します。このイメージをOpenShiftに事前にプルすることで、ワークスペースの起動時間を大幅に短縮します。また、まだ使ったことのないImage Pullerもあります。このロジックの一部を解消するのに、期待できそうです。
結論
要約すると、CodeReady Workspacesのデプロイを大規模に自動化することで、受講者のワークショップ体験を大幅に改善することができます。できるだけ多くのことを前もって行うことで、受講者はインストールやウォームアップなどを待たずに学習に取り掛かることができます。
この記事では、ワークショップの自動化とユーザーエクスペリエンスの向上のために作成した Ansibleプレイブックの一部を紹介しました。追加オプションとして以下のようなものがあります。
- 他のオペレーター(Strimzi、Jaegerなど)をデプロイする。
- ワークショップ用のカスタムKeycloakレルムを作成する。
- ワークショップの他のコンポーネントが正しくデプロイされているかどうかを確認する。
Deploy Quarkus Workshop into an OpenShift 4 Cluster playbookをご覧ください。他にも利用できるものがあるかもしれません!また、新規開発者のオンボーディングの例に興味がある方は、CodeReady Workspaces Delivers Kubernetes-Native IDEの記事を参照してください。