TeamCity On-Premises 2026.2 Help

高可用性のためのマルチノードセットアップ

TeamCity サーバーは、高可用性と柔軟な負荷分散のために複数のノード (またはサーバー) を使用するように構成できます。 TeamCity ノードのクラスターを設定し、各ノードがビルドからのデータ処理や VCS リポジトリからの変更収集など、異なるタスクを担当するようにできます。 または、すべての作業を行うメインノードと、読み取り専用インターフェースを提供するセカンダリノードを維持することもできます。 メインノードがダウンした場合、すべてのデータ処理を最小限のダウンタイムでセカンダリノードに切り替えることができます。

マルチノードセットアップの主なユースケースは高可用性 (HA) の実現であるため、この記事では HA クラスターの構成に焦点を当てます。 ただし、複数の TeamCity ノードを使用する任意のセットアップにも同じメソッドを使用できます。たとえば、複数のマシン間で負荷を分散できます。

メインノードとセカンダリノード

TeamCity クラスターには、 メインノードと複数の セカンダリノードを含めることができます。 メインノードは優先ノードであり、デフォルトではすべての受信 HTTP 要求を受信します。 また、ビルドの開始などの重要なバックグラウンドタスクも実行します。 セカンダリノードは主に、フェイルオーバーに必要なバックアップサーバーとして機能します。 負荷分散とパフォーマンスの最適化を向上させるために、 追加の責任を付与することもできます。

二つのノードを使用した TeamCity セットアップ

高可用性セットアップ

前提条件

基本的な HA セットアップには、次のコンポーネントが含まれている必要があります。

  • 専用データベースサーバー: サポートされているデータベースのリストにある外部データベースサーバー。

  • TeamCity データディレクトリ用の専用サーバー: データディレクトリは、NFS や SMB などのネットワーク経由でノードと共有する必要があります。

  • TeamCity ノード用に少なくとも 2 台のサーバー と、マウントされた 共有データディレクトリ: 両方のサーバーには同じまたは同等のハードウェアが必要です。 そうしないと、セカンダリノードのパフォーマンスが低下すると、フェイルオーバー時にパフォーマンスが大幅に低下する可能性があります。

  • TeamCity ノード上のローカルストレージ: TeamCity のインストール、およびログとローカルキャッシングの保存に必要です。 キャッシュのサイズを見積もるには、現在のインストールの <TeamCity データディレクトリ>/system/caches ディレクトリのサイズを参照してください。

  • 専用リバース HTTP プロキシサーバー

高可用性セットアップに必要なサーバーマシンの最小数は 5 です: データベース、ネットワークストレージサーバー、二つの TeamCity ノード、リバース HTTP プロキシ用サーバーです。 よりシンプルな負荷分散ソリューションは、より少ないマシンで実現できる場合があります。

共有データディレクトリ

メイン TeamCity ノードとセカンダリノードは、同じ TeamCity データディレクトリにアクセスして共有できる必要があります。

共有データディレクトリの設定に関する主な推奨事項は次のとおりです。

  • 高可用性のセットアップでは、メインノードがダウンした場合でもアクセスできるように、パフォーマンスの良い別のマシンに保存します。

  • すべての TeamCity ノードのマシンが、読み取り/書き込みモードでアクセスできる必要があります。

  • 一般的なデータディレクトリのマウントオプションは、SMB と NFS です。 TeamCity はデータディレクトリを通常のファイルシステムとして使用するため、すべての基本的なファイルシステム操作がサポートされている必要があります。

  • I/O 操作数または I/O ボリュームの制限は、ストレージまたはマウントオプションによって制限されるべきではありません。

  • ストレージソリューションのパフォーマンスガイドラインを確認してください。 例: サーバーとストレージ間のネットワーク接続の MTU を増やすと、通常、アーティファクトの転送速度が向上します。

  • データディレクトリマウントでネットワーククライアントキャッシュを無効化

    • すべてのノードが共有データディレクトリの現在の状態を遅滞なく確認することが重要です。 そうでない場合、動作が不安定になり、ビルドログが頻繁に破損する可能性があります。

    • TeamCity ノードが Windows 上で実行され、SMB プロトコル経由でデータディレクトリを共有している場合は、 この記事に記載されているすべてのレジストリ鍵が、すべての TeamCity ノードで 0 に設定されていることを確認してください。

    • データディレクトリが NFS 経由で共有されている場合、すべてのノードのマウント設定に次のオプションがあることを確認してください: lookupcache=positive

必須 JVM オプション

TeamCity サーバーノードでは、次の JVM オプションを構成する必要があります:

teamcity.サーバー.nodeId=<ノード_ID>

TeamCity ノードの一意の識別子で、UI と構成ファイルで使用されます。

teamcity.サーバー.rootURL=<ノード_ルート_URL>

TeamCity ノードのルート URL で、通常は http://<ノード_ホスト名> の形式です。 URL はノード間通信に必要であり、ファイアウォールは、あるノードから別のノードへのこの URL に対する接続を許可するように構成する必要があります。

teamcity.data.パス=<TeamCity データディレクトリ>

(任意) 共有 TeamCity データディレクトリのマウントポイントへのパス。

teamcity.node.data.パス=<ノード固有のデータディレクトリ>

ノード固有の TeamCity データディレクトリへのパスで、ノード固有の構成とキャッシング用に各ノード上にあるローカルストレージです。

teamcity.サーバー.responsibilities=<責務リスト>

(オプション) このノードに割り当てる 責任のコンマ区切りのリスト。

JVM オプションは、 TEAMCITY_SERVER_OPTS 環境変数を使用して構成できます。その値は、 -D<JVM オプション>=<値> フォーマットの設定をスペースで区切ったリストです。

HA セットアップの構成

このセクションは、次の前提に基づいています。

これで、単一サーバーのセットアップから高可用性クラスターのセットアップへの移行を進めることができます。

二つのノードで構成される TeamCity クラスターを構成するには、次の手順に従います:

  1. 両方のノードにインストールされている TeamCity サーバーのバージョンが同じで、データディレクトリのバージョンに対応していることを確認してください。

  2. 各ノードの ID を選択します (たとえば、ホスト名に基づく短い ID)。

  3. 各ノードに TEAMCITY_SERVER_OPTS 環境変数を作成します。 この変数には、次の引数が必要です。

    -Dteamcity.server.nodeId=<node_ID> -Dteamcity.server.rootURL=<node_root_URL> -Dteamcity.data.path=<TeamCity Data Directory> -Dteamcity.node.data.path=<Node-specific Data Directory>

  4. 通常の TeamCity スクリプトを使用するか、TeamCity サービス経由で両方のノードを起動します。

  5. いずれかのサーバーで TeamCity 管理 | ノード構成 ページを開き、メインにするノードに対して メイン TeamCity ノードの役割を有効化します。

  6. リバース HTTP プロキシの構成に進みます。

プロキシ構成

リバース HTTP プロキシは、TeamCity ユーザーおよび ビルドエージェント向けの単一エンドポイントとして機能します。 これは、クラスター全体の HTTPS 接続設定を構成するのにも適しています。

TeamCity と併用すると、プロキシサーバーは受信リクエストのロードバランサーとしても機能します。 リクエストの送信先を決定し、対応する上流サーバーにルーティングできます。 この記事では、最も一般的なプロキシサーバーである NGINX、NGINX Plus、HAProxy のプロキシ構成の例を示します。

defaults mode http timeout connect 240s timeout client 1200s timeout server 1200s frontend http-in bind *:80 stats enable stats uri /healthz option httplog log /dev/log local0 info # Uncomment if logging to stdout is desired (e.g. when running in a containerized environment) #log stdout local0 info option http-buffer-request declare capture request len 40000000 http-request capture req.body id 0 capture request header user-agent len 150 capture request header Host len 15 capture cookie X-TeamCity-Node-Id-Cookie= len 100 http-request add-header X-TeamCity-Proxy "type=haproxy; version=2023.05" http-request set-header X-Forwarded-Host %[req.hdr(Host)] acl node_id_cookie_found req.cook(X-TeamCity-Node-Id-Cookie) -m found acl browser req.hdr(User-Agent) -m sub Mozilla default_backend clients_not_supporting_cookies use_backend clients_with_node_id_cookie if node_id_cookie_found use_backend clients_supporting_cookies if browser backend clients_with_node_id_cookie # this backend handles the clients that provided the "X-TeamCity-Node-Id-Cookie" cookie # clients that do so are TeamCity agents and browsers handling HTTP requests asking to switch to a specific node cookie X-TeamCity-Node-Id-Cookie http-request disable-l7-retry if METH_POST METH_PUT METH_DELETE retry-on empty-response conn-failure response-timeout 502 503 504 retries 5 option httpchk GET /healthCheck/ready default-server check fall 6 inter 10000 downinter 5000 server NODE1 {node1_hostname} cookie {node1_id} server NODE2 {node2_hostname} cookie {node2_id} backend clients_supporting_cookies # this backend is for the browsers without "X-TeamCity-Node-Id-Cookie" # these requests will be served in a round-robin manner to a healthy server balance roundrobin option redispatch cookie TCSESSIONID prefix nocache http-request disable-l7-retry if METH_POST METH_PUT METH_DELETE option httpchk http-check connect http-check send meth GET uri /healthCheck/preferredNodeStatus http-check expect status 200 default-server check fall 6 inter 10000 downinter 5000 on-marked-down shutdown-sessions server NODE1 {node1_hostname} cookie n1 weight 50 server NODE2 {node2_hostname} cookie n2 weight 50 backend clients_not_supporting_cookies # for compatibility reasons requests from non browser clients are always # routed to a single node (the first healthy) balance first option redispatch http-request disable-l7-retry if METH_POST METH_PUT METH_DELETE option httpchk http-check connect http-check send meth GET uri /healthCheck/preferredNodeStatus http-check expect status 200 default-server check fall 6 inter 10000 downinter 5000 on-marked-down shutdown-sessions server NODE1 {node1_hostname} server NODE2 {node2_hostname}
events { worker_connections 10000; } http { upstream round_robin { zone round_robin 1m; server {node1_hostname}; server {node2_hostname}; sticky cookie X-TeamCity-RoundRobin-Cookie path=/; } upstream first_available { zone first_available 1m; server {node1_hostname} weight=100; server {node2_hostname} weight=1; } upstream sticky_route { zone sticky_route 1m; server {node1_hostname} route={node1_id}; server {node2_hostname} route={node2_id}; sticky route $node_id; } map $http_user_agent $browser { default 0; "~*Mozilla*" 1; } map $http_cookie $node_id_cookie { default 0; "~*X-TeamCity-Node-Id-Cookie" 1; } map "$browser$node_id_cookie" $backend { 00 @clients_not_supporting_cookies; 10 @clients_supporting_cookies; 01 @clients_with_node_id_cookie; 11 @clients_with_node_id_cookie; } map $http_cookie $node_id { default ''; "~*X-TeamCity-Node-Id-Cookie=(?<node_name>[^;]+)" $node_name; } map $http_upgrade $connection_upgrade { # WebSocket support default upgrade; '' ''; } proxy_read_timeout 1200; proxy_connect_timeout 240; client_max_body_size 0; # maximum size of an HTTP request. 0 allows uploading large artifacts to TeamCity server { listen 80; server_name {proxy_server_hostname}; status_zone status_page; set $proxy_header_host $host; set $proxy_descr "type=nginx_plus; version=2023.05"; location / { try_files /dev/null $backend; } location @clients_with_node_id_cookie { # this backend handles the clients which provided the cookie with name "X-TeamCity-Node-Id-Cookie" # such clients are TeamCity agents and browsers handling HTTP requests asking to switch to a specific node proxy_pass http://sticky_route; health_check uri=/healthCheck/ready; proxy_next_upstream error timeout http_503 http_502 non_idempotent; proxy_intercept_errors on; proxy_set_header Host $host:$server_port; proxy_redirect off; proxy_set_header X-TeamCity-Proxy $proxy_descr; proxy_set_header X-Forwarded-Host $http_host; # necessary for proper absolute redirects and TeamCity CSRF check proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Upgrade $http_upgrade; # WebSocket support proxy_set_header Connection $connection_upgrade; # WebSocket support } location @clients_supporting_cookies { # this backend is for the browsers without "X-TeamCity-Node-Id-Cookie" # these requests will be served in a round-robin manner to a healthy server proxy_pass http://round_robin; health_check uri=/healthCheck/preferredNodeStatus; proxy_next_upstream error timeout http_503 http_502 non_idempotent; proxy_intercept_errors on; proxy_set_header Host $host:$server_port; proxy_redirect off; proxy_set_header X-TeamCity-Proxy $proxy_descr; proxy_set_header X-Forwarded-Host $http_host; # necessary for proper absolute redirects and TeamCity CSRF check proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Upgrade $http_upgrade; # WebSocket support proxy_set_header Connection $connection_upgrade; # WebSocket support } location @clients_not_supporting_cookies { # for compatibiity reasons requests from non browser clients are always # routed to a single node (the first healthy) proxy_pass http://first_available; health_check uri=/healthCheck/preferredNodeStatus; proxy_next_upstream error timeout http_503 http_502 non_idempotent; proxy_intercept_errors on; proxy_set_header Host $host:$server_port; proxy_redirect off; proxy_set_header X-TeamCity-Proxy $proxy_descr; proxy_set_header X-Forwarded-Host $http_host; # necessary for proper absolute redirects and TeamCity CSRF check proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Upgrade $http_upgrade; # WebSocket support proxy_set_header Connection $connection_upgrade; # WebSocket support } } }
events { worker_connections 10000; } http { upstream {main_node_id} { server {main_node_hostname}; server {secondary_node_hostname} backup; } upstream {secondary_node_id} { server {secondary_node_hostname}; server {main_node_hostname} backup; } upstream web_requests { server {main_node_hostname}; server {secondary_node_hostname} backup; } map $http_cookie $backend_cookie { default "{main_node_id}"; "~*X-TeamCity-Node-Id-Cookie=(?<node_name>[^;]+)" $node_name; } map $http_user_agent $is_agent { default @users; "~*TeamCity Agent*" @agents; } map $http_upgrade $connection_upgrade { # WebSocket support default upgrade; '' ''; } proxy_read_timeout 1200; proxy_connect_timeout 240; client_max_body_size 0; # maximum size of an HTTP request. 0 allows uploading large artifacts to TeamCity server { listen 80; server_name {proxy_server_hostname}; set $proxy_header_host $host; set $proxy_descr "type=nginx; version=2023.05"; location / { try_files /dev/null $is_agent; } location @agents { proxy_pass http://$backend_cookie; proxy_next_upstream error timeout http_503 non_idempotent; proxy_intercept_errors on; proxy_set_header Host $host:$server_port; proxy_redirect off; proxy_set_header X-TeamCity-Proxy $proxy_descr; proxy_set_header X-Forwarded-Host $http_host; # necessary for proper absolute redirects and TeamCity CSRF check proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Upgrade $http_upgrade; # WebSocket support proxy_set_header Connection $connection_upgrade; # WebSocket support } location @users { proxy_pass http://web_requests; proxy_next_upstream error timeout http_503 non_idempotent; proxy_intercept_errors on; proxy_set_header Host $host:$server_port; proxy_redirect off; proxy_set_header X-TeamCity-Proxy $proxy_descr; proxy_set_header X-Forwarded-Host $http_host; # necessary for proper absolute redirects and TeamCity CSRF check proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Upgrade $http_upgrade; # WebSocket support proxy_set_header Connection $connection_upgrade; # WebSocket support } } }

適切なプロキシサーバーの選択

TeamCity はさまざまなタイプのプロキシサーバーと連携できます。 ただし、 HAProxy および NGINX Plus は、アクティブなヘルスチェックとスティッキーセッションをサポートするため、これらのサーバーの方が推奨されます。 これらの機能は、異なるノード間でのユーザーリクエストの ラウンドロビン (TeamCity 2023.05+ でサポート) に不可欠です。

比較すると、標準モジュールを備えた通常の NGINX プロキシにはこれらの機能がないため、ラウンドロビンの構成に使用できません。

さらに、通常の NGINX では、構成ファイル内でメインノードとセカンダリノードを明示的に区別する必要があります (メインノードがリストの最初にある必要があります)。 この要件により、メインノードがその責任をセカンダリノードに移管するとき (たとえば、フェールオーバーの場合)、ノードのロールを手動で更新する必要があります。 HAProxy サーバーと NGINX Plus サーバーでは、同じシナリオで構成ファイルを手動で更新する必要はありません。

最後に、 HAProxy および NGINX Plus プロキシサーバーの構成ファイルは、特にクラスターに新しいノードを追加する場合に保守が容易になります。

プロキシバージョンとサーバーの一致

上記のサンプル プロキシ構成では、特別な X-TeamCity-Proxy ヘッダーが設定されます。 このヘッダーは、リクエストが適切に構成されたプロキシを経由していることを TeamCity に通知します。

X-TeamCity-Proxy ヘッダーは、プロキシ設定のバージョンも定義します。 このバージョンが現在の TeamCity バージョンと互換性がない場合、TeamCity は プロキシ構成のバージョン不一致 ヘルスレポートを表示します。 プロキシ設定を確認し、 プロキシ構成 セクションに示されている設定と同様であることを確認します。

ラウンドロビン

バージョン 2023.05 以降、メイン TeamCity ノードと、 UI アクションの処理とユーザーリクエストの負荷分散の責任が設定されたすべてのセカンダリノードがラウンドロビンに参加します。

プロキシは、最初のブラウザー要求を参加ノードのいずれかにランダムにルーティングします。 後続の HTTP リクエストは同じノード (スティッキーセッション) に送信されます。 この動作により、ユーザーリクエストで発生した負荷は異なるノード間で配布済みになり、TeamCity がより多くの同時 HTTP リクエストを処理することを可能にします。 さらに、ラウンドロビンにより、 フェイルオーバーまたは計画されたノード再起動時のユーザーエクスペリエンスが向上します。 たとえば、単一のノードを再起動する必要がある場合、このノードに割り当てられているユーザーのみが影響を受けます。 そして、ノードが利用できなくなったことをプロキシサーバーが検出するとすぐに、これらすべてのユーザーは他のノードに分散されます。

リクエストを任意のノードにランダムに割り当てるのではなく、特定のノードで処理する必要がある場合は、TeamCity UI フッターのノードセレクターを使用するか、リクエストクエリ文字列に __nodeId=<ノードの id> リクエストパラメーターを追加します。

ラウンドロビンリストにノードを追加したり、ラウンドロビンリストからノードを除去したりするには、 UI アクションの処理とユーザーリクエストの負荷分散の役割の状態を変更します。 プロキシ構成を変更する必要はありません。

ドメイン分離プロキシ構成

ドメイン分離モードでは、アーティファクトを提供するための専用ドメインを構成する必要があります。 このドメインからプロキシアドレスを指す新しいレコードを DNS に追加してください。たとえば、プロキシ URL を指す 正規名 レコードにできます。

フェイルオーバー

フェイルオーバー時に、クラッシュまたはメンテナンスによりメインノードが使用できなくなった場合、セカンダリノードに メイン TeamCity ノードの責任を付与し、一時的または永続的にメインノードとして動作させることができます。

各セカンダリノードは、現在のメインノードのアクティビティを追跡し、メインノードが数分間 (デフォルトでは 3 分間) 非アクティブになると、対応するヘルスレポートを表示します。 メイン TeamCity ノードの責任は、TeamCity UI または REST API 経由で別のノードに再割り当てできます。 ただし、この非アクティブ状態が計画されたものではない場合 (つまり、メインノードがクラッシュした場合)、非アクティブなノード上で TeamCity サーバープロセスが実行されたまま残っていないことを確認することが重要です。 このようなプロセスを検出した場合は、 メイン TeamCity ノードの責任を再割り当てする前に、それらを停止する必要があります。

標準の NGINX プロキシサーバーを使用する場合は、 リバースプロキシ構成内のノード ID とホスト名を更新し、 メイン TeamCity ノードの責任を切り替えた後にプロキシサーバー構成を再読み込みします。 HAProxy および NGINX Plus プロキシサーバーでは、手動で構成を更新する必要はありません。

要約すると、フェイルオーバーの場合は次の手順に従います。

  1. セカンダリノードでメインノードが使用できないことに関するサーバーのヘルスレポートを待ちます。

  2. メインノードが停止していることを確認してください。

  3. セカンダリノードの メインノード責任を切り替えます。

  4. (通常の NGINX が使用されている場合) リバースプロキシ構成のメインノード ID を更新し、構成を再ロードします。

REST API によるノードの監視と管理

TeamCity 2022.10 以降、REST API を使用してノードのステータスを確認し、ノードの責任を再割り当てできます。

すべてのオンラインノードのリストを取得するには、次を使用します。

GET /app/rest/server/nodes?locator=state:online

メインノード責任をセカンダリノードに割り当てるには、次を使用します。

PUT /app/rest/server/nodes/id:<node id>/enabledResponsibilities/MAIN_NODE

curl を使用した同じ例:

curl \ -X PUT \ -H "Content-Type: text/plain" \ -H "Origin: <host>:<port>" \ --data-raw "true" \ --header “Authorization: Bearer <token-value>” \ "https://<host>:<port>/app/rest/server/nodes/id:<node id>/enabledResponsibilities/MAIN_NODE"
GET /app/rest/server/nodes/id:<node id>/effectiveResponsibilities

ノード構成

認証とライセンス

メインノードとセカンダリノードは同じライセンスで動作します。

セカンダリノードは、メインノードと同じ認証設定を使用します。 ただし、ユーザーはセカンダリノードにルーティングされた後、再度ログインするよう求められる場合があります。 これは、(1) ユーザーがログイン画面で記憶するオプションを選択しなかった場合、および (2) SSO 認証が構成されていない場合の 2 つの場合に発生します。

グローバル設定

セカンダリノードは、メインノードと同じグローバル設定 (アーティファクトへのパス、バージョン管理設定など) を使用します。

責任

デフォルトでは、新しく起動されたセカンダリノードは読み取り専用のユーザーインターフェースを提供し、バックグラウンドアクティビティを実行しません。 管理 | サーバー管理 | ノード構成 の各セカンダリノードに次の追加の責任を割り当てることができます。

ユーザーがビルドとエージェントで最も一般的なアクションを実行できるようにするには、 UI アクションを処理することとユーザーリクエストの負荷分散責任を有効化します。

ノードの責任をいつでも有効または無効にできます。

セカンダリノードでのビルド生成データの処理

一つ以上のセカンダリノードを使用して、TeamCity エージェントからのトラフィックを処理できます。 これにより、関連する負荷をメイン TeamCity ノードから別のマシンに移動でき、数百の同時実行中でアクティブにログ記録しているビルドを処理する際の TeamCity のパフォーマンスが向上します。

一般に、1 つのノードに 400 を超えるエージェントが接続されていない限り、ビルドを実行するために別のノードは必要ありません。 セカンダリノードを使用すると、セットアップで処理できるエージェントの数を大幅に増やすことができます。

初めてセカンダリノードに ビルドによって生成されたデータの処理の責任を割り当てると、新しく開始されたすべてのビルドがこのノードにルーティングされます。 既存の実行中ビルドは、メインノードで引き続き実行されます。 責任を無効化すると、新しく開始されたビルドだけがメインノードに切り替えられます。 セカンダリノードですでに実行されていたビルドは、そこで実行され続けます。
この責任を複数のセカンダリノードに割り当てると、ビルドはこれらのノード間で均等に配布済みになります。

セカンダリノードでの VCS リポジトリのポーリング

初期状態では、メイン TeamCity ノードのみが VCS リポジトリをポーリングして新しいコミットを確認します。 複数のノードで VCS リポジトリのポーリングの責任を有効にすると、この潜在的に遅いアクティビティを分散し、新しいビルドを開始するまでの待ち時間を短縮できます。

メインノードに設定されたコミットフックは変更する必要がなく、VCS ポーリングをセカンダリノードに委譲した後も機能し続けます。

セカンダリノードでのトリガー処理

多数のビルドエージェントがあるセットアップでは、メインノードの CPU のかなりの量がビルドトリガーの継続的な処理に割り当てられます。 1 つ以上のセカンダリノードに対して ビルドトリガーの処理責任を有効にすると、トリガー処理タスクと CPU 負荷をメインノードと担当するセカンダリノードの間で分散できます。 TeamCity はトリガーを自動で配布済みにしますが、各ノードに現在割り当てられているトリガーを確認できます。

UI アクションを処理することとユーザーリクエストの負荷分散

この責任は、セカンダリノードでのユーザーアクションを許可する責任があります。 これは、メインノードがダウンしている場合やメンテナンス中である場合に特に役立ちます。

この責任を有効にすると、 round-robin に参加しているノードのリストにもノードが追加されます。

メインノードの責任

セカンダリノードに メイン TeamCity ノードの責任を割り当てることができます。 この責任はデフォルトで現在のメインノードに属しますが、このノードが使用できなくなると空きになります。 任意のセカンダリノードをこの責任に割り当てると、そのノードはメインノードになり、さらに UI アクションの処理とユーザーリクエストの負荷分散の責任を受け取ります。 実行中のすべてのビルドは、中断することなく処理を継続します。 セットアップで プロキシが構成されている場合、ビルドエージェントは新しいメインノードにシームレスに再接続します。
以前のメインノードが再び起動すると、 メイン TeamCity ノードの責任はすでに別のノードによって占有されているため、そのノードはセカンダリノードになります。 必要に応じて、上記のプロシージャを繰り返して、これらのノード間でロールを切り替えることができます。

コマンドラインでの責任の設定

次の JVM オプションを使用してサーバーの責任を定義できます。

teamcity.server.responsibilities=<responsibilities_list>

サーバーの環境で、JVM オプションを TEAMCITY_SERVER_OPTS 環境変数に追加し、責任をコンマ区切りのリストとして指定します。 例:

-Dteamcity.server.responsibilities=CAN_PROCESS_BUILD_MESSAGES,CAN_CHECK_FOR_CHANGES,CAN_PROCESS_BUILD_TRIGGERS,CAN_PROCESS_USER_DATA_MODIFICATION_REQUESTS

次の責任を有効にできます。

識別子

責任

ビルドメッセージを処理できる

ビルドによって生成されたデータの処理

変更を確認できる

VCS リポジトリのポーリング

ビルドトリガーを処理できる

ビルドトリガーの処理

ユーザーデータ変更リクエストを処理できる

UI アクションを処理することとユーザーリクエストの負荷分散

メインノード

メイン TeamCity ノード

サーバーの責任がコマンドラインで設定されている場合は、次の制限が適用されることに注意してください。

  • 処理するビルドの最大割合各ノードに割り当てられるトリガーをコマンドラインから指定することはできません。 これらの責任設定は、UI または REST API からのみ使用できます。

  • ユーザーデータ変更リクエストを処理できる 責任が有効になっている場合は、UI または REST API を使用してサーバーの責任を編集できますが、これはサーバーに直接接続している場合に限られます。 さらに、これらの変更は一時的なものにすぎません (ノードが再起動するとリセットされます)。

内部プロパティ

すべての TeamCity ノードは、 共有データディレクトリに保存される共通の内部プロパティと、ノード固有のデータディレクトリに保存される固有のプロパティの両方に依存します。 ノード固有のプロパティは優先度が高く、競合が発生した場合に共通の値を上書きします。

特定のセカンダリノードの共通プロパティを無効にするには、次の構文を使用してプロパティを渡します: -<プロパティ名>

セカンダリノードのメモリ設定

セカンダリノードには、メインノードと同じメモリ設定が必要です。 メインノードに TEAMCITY_SERVER_MEM_OPTS 環境変数をすでに設定している場合は、セカンダリノードにも同じ変数を使用してください。 メインノードで 64 ビット JVM を使用している場合は、セカンダリノードでも 64 ビット JVM を使用する必要があります。

環境変数

次の環境変数を使用して TeamCity サーバーノードを構成できます:

変数

説明

TEAMCITY_DATA_PATH

共有 TeamCity データディレクトリへのパス。

TEAMCITY_SERVER_OPTS

(必須) サーバー JVM オプション (必須 JVM オプションを参照)。

TEAMCITY_SERVER_MEM_OPTS

サーバー JVM メモリオプション (JVM オプションを参照)。

ノードの管理

プロジェクトインポート

プロジェクトはメインノードにのみインポートできます。 セカンダリノードは、再起動することなく、ランタイムにインポートされたデータを検出します。

クリーンアップ

TeamCity クリーンアップタスクは任意の TeamCity ノードでスケジュールできますが、実行されるのはメインノードのみです。 マルチノード構成でも単一ノード構成でも、セカンダリノードが操作を処理している間にタスクを実行できます。

プラグインの使用

セカンダリノードは、メインノードで有効になっているすべてのプラグインにアクセスできます。 また、新しくアップロードされたプラグインも監視します。 プラグインがメインノードにアップロードされたことをセカンダリノードが検出すると、 管理 | プラグイン ページにそれぞれの通知が表示されます。 プラグインがサポートしている場合、セカンダリノードを再起動することなく実行時に再ロードできます — それぞれのヒントが UI に表示されます。

セカンダリノードの自動追加

セカンダリノードの基本構成を提供する TeamCity サーバーの 環境変数を活用することで、手動での介入を最小限に抑えて (たとえばスクリプトで)、セカンダリノードのインスタンスをスピンアップできます。

自動化に適した方法でセカンダリノードを作成するには、次の手順に従います。

  1. 配布パッケージをダウンロードしてインストールするか、適切な Docker イメージをプルして、TeamCity サーバーソフトウェアを準備します。 TeamCity ソフトウェアのバージョンが、他のノードで実行されているバージョンと同じであることを確認してください。

  2. 共有 TeamCity データディレクトリをマウントします (たとえば、NFS または SMB を使用)。

  3. TEAMCITY_DATA_PATH 環境変数を設定して、共有 TeamCity データディレクトリへのパスを指定します。

  4. 次のように JVM オプションのスペース区切りリストを使用して TEAMCITY_SERVER_OPTS 環境変数を設定することにより、ノードの JVM オプションを指定します。

    TEAMCITY_SERVER_OPTS = -Dteamcity.server.nodeId=<node_ID> -Dteamcity.server.rootURL=<node_URL> -Dteamcity.node.data.path=<Node-specific Data Directory> -Dteamcity.server.responsibilities=<responsibilities_list>

    説明:

    • <ノード_ID> はノードの一意の ID であり、このノード専用に生成される必要があります。

    • <ノード_URL> はセカンダリノードのルート URL であり、メインノードからアクセスできる必要があります。

    • <ノード固有のデータディレクトリ> は、ノード固有の TeamCity データディレクトリへのパスです。

    • <責務リスト> は、このノードで有効にする 責任のコンマ区切りのリストです。

  5. 必要に応じて、 TEAMCITY_SERVER_MEM_OPTS 環境変数を設定して JVM メモリオプションを指定します。

  6. 通常の TeamCity スクリプトを使用するか、TeamCity サービスを使用するか、TeamCity サーバー Docker コンテナーを実行して、TeamCity サーバーを起動します。

アップグレード/ダウングレード

メイン TeamCity ノードとすべてのセカンダリノードは、同じバージョンにすることをお勧めします。 場合によっては、たとえば、メインノードのマイナーアップグレード中など、メインノードとセカンダリノードが異なるバージョンを短期間実行している可能性があります。 セカンダリノードとメインノードのバージョンが異なる場合、対応するヘルスレポートが両方のノードに表示されます。

マイナーバージョンへのアップグレード (バグ修正リリース)の場合、TeamCity のデータフォーマットは同じままなので、メインノードとセカンダリノードは課題が発生せずに実行されているはずです。 メイン TeamCity ノードをアップグレードしてから、セカンダリノードを 手動で、または 自動更新でアップグレードできます。

メインノードのメジャーバージョンへのアップグレード の場合、TeamCity のデータフォーマットが変更されます。 そのため、新しいバージョンのメインノードが起動するとすぐに、セカンダリノードはメインノードのデータ形式が異なることを検出し、読み取り専用モードに切り替わります。 セカンダリノードが読み取り専用になるまでには、しばらく時間がかかる場合があります。 この間、メインノードは、他のすべてのノードがデータを変更しなくなるまで待機します。

マルチノードセットアップ内のノードを TeamCity のメジャーバージョンに アップグレード するには、次のステップに従います:

  1. メイン TeamCity ノードを アップグレードします。 ノードのアップグレード手順は、スタンドアロンサーバーのアップグレード手順と同じです。

  2. すべてが正しく機能し、エージェントがメインノードに接続していることを確認します (エージェントは、セカンダリノードにルーティングされるはずだったデータをメインノードに再ルーティングします)。

  3. セカンダリノードの TeamCity を同じバージョンにアップグレードします。 メインノードを異なるメジャーバージョンにアップグレードした後にセカンダリノードを再起動した場合、そのノードは手動でアップグレードする必要があります。 自動アップグレードは利用できなくなります(TW-98862(英語) を参照)。

マルチノード設定でノードを ダウングレード には、次の手順に従います。

  1. メインノードとセカンダリノードをシャットダウンします。

  2. バックアップからの データを復元する (アップグレード中にデータ形式が変更された場合のみ)。

  3. メインノード上の TeamCity ソフトウェアをダウングレードします。

  4. メイン TeamCity ノードを起動し、すべてが正常に動作することを確認します。

  5. セカンダリノード上の TeamCity ソフトウェアを、メインノードと同じバージョンにダウングレードします。

  6. セカンダリノードを起動します。

TeamCity エージェントはアップグレード/ダウングレードを自動的に実行します。

起動/停止

任意の TeamCity ノードは、通常の TeamCity スクリプト (teamcity-server.bat または teamcity-サーバー.sh) または Windows サービスを使用して起動/停止できます。 環境変数 [TEAMCITY_DATA_PATH]、[TEAMCITY_SERVER_MEM_OPTS]、[TEAMCITY_SERVER_OPTS] は、すべての型のノードでサポートされています。

すべてのノードは、イベントのロギングに同じアプローチを使用します。 起動の状態は <TeamCity ホームディレクトリ>/logs/teamcity-server.log ファイルで確認できます。 または、ブラウザーで <ノードルート URL> を開いて TeamCity の始動画面を表示できます。

セカンダリノードとメインノードは、ビルドの実行中に停止または再起動できます。 それらはエージェント上で実行され続け、プロキシによって別のノードに再割り当てされるか、指定されたノードが再び起動するまで待機します。

バックアップ/復元

UI アクションの処理とユーザーリクエストの負荷分散の責任を持つ任意のノードで、 TeamCity UI からバックアップを開始できます。 コマンドラインから任意のノードでバックアップを開始することもできます。 バックアップの実行中、他のすべてのノードでは、クリーンアップのスケジュール設定、プロジェクトのインポート、別のバックアッププロセスの開始は許可されません。

復元操作はどちらのノードでも実行できますが、TeamCity データベースとデータディレクトリを使用しているすべてのノードが停止している場合に限ります。

マルチノードセットアップのヘルスレポート

専用記事の関連レポートを参照してください。

一般的な課題

Windows サービスからデータディレクトリにアクセスする際の問題

TeamCity が Windows 上でサービスとして実行されている場合、マップされたネットワークドライブ経由で TeamCity データディレクトリにアクセスできない場合があることに注意してください。 これは、Windows サービスがマップされたネットワークドライブを扱えず、TeamCity がデータディレクトリパスに UNC フォーマット (\\host\ディレクトリ) をサポートしていないために発生します。 この問題を回避するには、ネットワークドライブにシンボリックリンクを作成できる mklink を使用できます。

mklink /d "C:\<path to mount point>" "\\<host>\<shared directory name>\"

OS でリモートからローカルへのシンボリックリンク評価が有効になっていることを確認します。

fsutil behavior query SymlinkEvaluation

それらを有効にするには、次のコマンドを使用します。

fsutil behavior set SymlinkEvaluation R2L:1
2026 年 9 月 11 日