<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Armory Docs – Armory Scale Agent for Spinnaker and Kubernetes Concepts</title><link>/plugins/scale-agent/concepts/</link><description>Recent content in Armory Scale Agent for Spinnaker and Kubernetes Concepts on Armory Docs</description><generator>Hugo -- gohugo.io</generator><atom:link href="/plugins/scale-agent/concepts/index.xml" rel="self" type="application/rss+xml"/><item><title>Plugins: Armory Scale Agent Architecture</title><link>/plugins/scale-agent/concepts/architecture/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/plugins/scale-agent/concepts/architecture/</guid><description>
&lt;!-- the purpose is to list the bare minimum IT security needs to know to approve use in a corporate env; modeled after the CDaaS arch page-->
&lt;h2 id="key-components">Key Components&lt;/h2>
&lt;h3 id="scale-agent-plugin-for-clouddriver">Scale Agent plugin for Clouddriver&lt;/h3>
&lt;p>The Scale Agent plugin runs inside Clouddriver and manages migrated accounts and accounts created specifically for Scale Agent management. The plugin does not engage in outbound communication. Through Clouddriver, the plugin exposes an internally-accessible REST API that you can use to dynamically migrate and manage Kubernetes accounts.&lt;/p>
&lt;h3 id="scale-agent-service-for-kubernetes">Scale Agent service for Kubernetes&lt;/h3>
&lt;p>You Scale Agent service monitors your Kubernetes clusters and sends information to the Scale Agent plugin running inside Clouddriver.&lt;/p>
&lt;p>The Agent service sends the following information about the cluster it is watching to the Clouddriver plugin:&lt;/p>
&lt;ul>
&lt;li>Account properties as configured in &lt;code>kubernetes.accounts[]&lt;/code>.&lt;/li>
&lt;li>Kubernetes API server host, certificate fingerprint, and version.&lt;/li>
&lt;li>All the Kubernetes objects it is configured to watch and has permissions to access. You can ignore certain Kubernetes &lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/">kinds&lt;/a> (&lt;code>kubernetes.accounts[].omitKinds&lt;/code>) or configure specific kinds to watch (&lt;code>kubernetes.accounts[].kinds&lt;/code>).&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>The Agent service always scrubs data from &lt;code>Secret&lt;/code> in memory before it is sent and even before that data makes it onto the Armory Scale Agent&amp;rsquo;s memory heap.&lt;/p>
&lt;/blockquote>
&lt;h4 id="kubernetes-permissions-for-the-service">Kubernetes permissions for the service&lt;/h4>
&lt;p>The Agent service should have &lt;code>ClusterRole&lt;/code> authorization if you need to deploy pods across your cluster. If you only deploy pods only to a single namespace, the service needs &lt;code>Role&lt;/code> authorization.&lt;/p>
&lt;p>See &lt;a href="/plugins/scale-agent/concepts/service-permissions/"}>Kubernetes Permissions for the Armory Scale Agent&lt;/a> for detailed information.&lt;/p>
&lt;h2 id="communication-and-networking">Communication and networking&lt;/h2>
&lt;p>Communication from the Scale Agent service to the Clouddriver plugin occurs over gRPC port 9091. Communication between the service and the plugin must be &lt;code>http/2&lt;/code>. &lt;code>http/1.1&lt;/code> is &lt;em>not&lt;/em> compatible and causes communication issues between the Armory Agent service and Clouddriver plugin.&lt;/p>
&lt;p>Except for a local health check, the Agent service makes outbound calls only to the Clouddriver plugin over a single &lt;a href="https://grpc.io/">gPRC&lt;/a> connection. The connection can be over TLS or mTLS. You can terminate TLS:&lt;/p>
&lt;ol>
&lt;li>On Clouddriver: in the case of running the Armory Scale Agent in Spinnaker Service mode or if declaring &lt;code>spin-clouddriver-grpc&lt;/code> as a network load balancer.&lt;/li>
&lt;li>On a gRPC proxy that directs request to the &lt;code>spin-clouddriver-grpc&lt;/code> service.&lt;/li>
&lt;/ol>
&lt;p>The Clouddriver plugin uses the bidirectional communication channel to receive changes from Kubernetes accounts as well as send operations to the Armory Scale Agent service.&lt;/p>
&lt;p>See the &lt;a href="/plugins/scale-agent/concepts/communication/"}>Armory Scale Agent Communication With Clouddriver Instances in Kubernetes&lt;/a> page for detailed information.&lt;/p>
&lt;h2 id="security">Security&lt;/h2>
&lt;p>Since the Armory Scale Agent service does outbound calls only, you can have Agent services running on-premises or in public clouds such as AWS, GCP, Azure, Oracle, or Alibaba.&lt;/p>
&lt;p>What the Scale Agent service can do in the target cluster is limited by what it is running as:&lt;/p>
&lt;ul>
&lt;li>a &lt;code>serviceAccount&lt;/code> in Agent mode&lt;/li>
&lt;li>a &lt;code>kubeconfig&lt;/code> setup for infrastructure or Spinnaker service mode&lt;/li>
&lt;/ul>
&lt;p>Communications are secured with TLS and optionally mTLS.&lt;/p>
&lt;h2 id="whats-next">What&amp;rsquo;s next&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="/plugins/scale-agent/concepts/service-permissions/"}>Kubernetes Permissions for the Armory Scale Agent&lt;/a>&lt;/li>
&lt;li>&lt;a href="/plugins/scale-agent/concepts/communication/"}>Armory Scale Agent Communication With Clouddriver Instances in Kubernetes&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Plugins: Armory Scale Agent Communication With Clouddriver Instances in Kubernetes</title><link>/plugins/scale-agent/concepts/communication/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/plugins/scale-agent/concepts/communication/</guid><description>
&lt;h2 id="how-the-armory-scale-agent-plugin-communicates-with-clouddriver-instances">How the Armory Scale Agent plugin communicates with Clouddriver instances&lt;/h2>
&lt;figure>
&lt;img src="/images/scale-agent/k8s-clustering.png"
alt="Kubernetes clustering" width="75%" height="75%"/>
&lt;/figure>
&lt;p>At startup, Clouddriver registers a watch for the kind &lt;code>Endpoints&lt;/code> in the Kubernetes cluster where it is running for the namespace where Clouddriver is running. Objects of kind &lt;code>Endpoints&lt;/code> are automatically generated based on a Kubernetes Service. The plugin knows that there&amp;rsquo;s a Clouddriver Service for routing HTTP traffic to Clouddriver pods (usually named &lt;code>spin-clouddriver&lt;/code>). This means that the Clouddriver pod needs to mount a Kubernetes Service Account that has permissions to list and watch the kind &lt;code>Endpoints&lt;/code> in the current namespace. The Agent plugin does the equivalent of these calls at startup:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl auth can-i list endpoints
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kubectl auth can-i watch endpoints
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If permissions are in place, the plugin then does the equivalent of this call:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl get endpoints
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>From the returned collection, the plugin filters the entries based on these conditions:&lt;/p>
&lt;ol>
&lt;li>The endpoint Name should have the prefix &lt;code>spin-clouddriver&lt;/code>. This is configurable and is a prefix to be able to match several entries like the ones used in HA.&lt;/li>
&lt;li>Each entry should have a port named &lt;code>http&lt;/code>, which is configurable. This is to be able to differentiate between the port that Clouddriver uses to receive REST requests and the port it uses to listen for gRPC connections from Agent.&lt;/li>
&lt;/ol>
&lt;p>Information about discovered Clouddriver instances is kept in memory on each Clouddriver pod and is automatically updated by the watch mechanism. No polling is needed. The Kubernetes API server notifies the plugin when there are any changes.&lt;/p>
&lt;h2 id="operation-request-and-response-forwarding">Operation request and response forwarding&lt;/h2>
&lt;p>When a Clouddriver instance receives an operation for an account or Agent that is registered to a different Clouddriver instance, the plugin uses a combination of a database table and an in-memory map to determine where to forward the operation. Forwarding is done via REST requests.&lt;/p>
&lt;h3 id="exposed-endpoints">Exposed endpoints&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>&lt;code>GET &amp;lt;clouddriver host:port&amp;gt;/armory/clouddrivers&lt;/code>&lt;/p>
&lt;p>Sample response:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>[
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> baseUrl: &lt;span style="color:#ff79c6">&amp;#34;http://10.0.15.246:7002&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id: &lt;span style="color:#ff79c6">&amp;#34;spin-clouddriver-766c678c6c-scg68&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> lastUpdated: &lt;span style="color:#ff79c6">&amp;#34;2022-02-23T20:41:39.333Z&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ready: true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The field &lt;code>ready&lt;/code> matches the column &lt;code>Ready&lt;/code> of &lt;code>kubectl -n &amp;lt;spinnaker ns&amp;gt; get pods&lt;/code> for Clouddriver pods.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>POST &amp;lt;clouddriver host:port&amp;gt;/armory/agent/operations&lt;/code>&lt;/p>
&lt;p>Sample request body:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">&amp;#34;operation&amp;#34;&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;&amp;lt;toString() of protobuf Operation object&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;code>POST &amp;lt;clouddriver host:port&amp;gt;/armory/agent/operationresults&lt;/code>&lt;/p>
&lt;p>Sample request body:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">&amp;#34;result&amp;#34;&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;&amp;lt;toString() of protobuf OperationResult object&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol></description></item><item><title>Plugins: Dynamic Accounts Architecture and Features</title><link>/plugins/scale-agent/concepts/dynamic-accounts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/plugins/scale-agent/concepts/dynamic-accounts/</guid><description>
&lt;h2 id="overview-of-dynamic-accounts">Overview of Dynamic Accounts&lt;/h2>
&lt;p>Rather than &lt;a href="/plugins/scale-agent/reference/config/service-options/#configure-kubernetes-accounts">manually configure&lt;/a> each Scale Agent service with the Kubernetes accounts it should manage, you can use the Dynamic Accounts feature to migrate and manage your accounts. Dynamic Accounts provides:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Manual migration of Clouddriver Kubernetes accounts to the Scale Agent using a REST API&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Automatic migration of Clouddriver Kubernetes accounts using Clouddriver Account Management&lt;/p>
&lt;ul>
&lt;li>Automatic migration requires Armory Continuous Deployment 2.28+ or Spinnaker 1.28+.&lt;/li>
&lt;li>Clouddriver Account Management is not enabled by default in Spinnaker or Armory Continuous Deployment. See Spinnaker&amp;rsquo;s &lt;a href="https://spinnaker.io/docs/setup/other_config/accounts/">Clouddriver Account Management&lt;/a> for how to enable this feature in your Spinnaker instance.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="rest-api">REST API&lt;/h3>
&lt;p>The Dynamic Accounts REST API provides endpoints to create, delete, get, migrate, and update Kubernetes accounts. You can&amp;rsquo;t access these endpoints through Gate. You should have &lt;code>kubectl&lt;/code> access to your Spinnaker cluster and &lt;code>port-forward&lt;/code> to be able to call the API.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubectl port-forward deployment/spin-clouddriver 7002:7002 -n spinnaker
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can then access endpoints via &lt;code>http://localhost:7002&lt;/code>.&lt;/p>
&lt;h3 id="how-to-enable-and-use-dynamic-accounts">How to enable and use Dynamic Accounts&lt;/h3>
&lt;p>First, familiarize yourself with the architecture and features in this guide. Then you can:&lt;/p>
&lt;ol>
&lt;li>&lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/enable/"}>Enable and Configure Dynamic Accounts in the Armory Scale Agent&lt;/a>&lt;/li>
&lt;li>&lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/migrate-accounts/"}>Migrate Clouddriver Kubernetes Accounts to the Armory Scale Agent&lt;/a>&lt;/li>
&lt;li>&lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/manage-accounts/"}>Manage Kubernetes Accounts in the Armory Scale Agent&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="dynamic-accounts-glossary">Dynamic Accounts glossary&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Account&lt;/strong>: an abstraction of a target cluster or target set of namespaces within a cluster&lt;/li>
&lt;li>&lt;strong>Credentials source&lt;/strong>: any source from which credentials/accounts are read&lt;/li>
&lt;li>&lt;strong>Endpoint&lt;/strong>: the URL segment after the Clouddriver root&lt;/li>
&lt;li>&lt;strong>Migrate an account&lt;/strong>: move a Clouddriver-managed account to the Scale Agent for management&lt;/li>
&lt;li>&lt;strong>Request&lt;/strong>: an instruction that isn’t fulfilled immediately and can have different outcomes; a request can be done through HTTP by the admin or internally by one of the services.&lt;/li>
&lt;/ul>
&lt;h2 id="architecture">Architecture&lt;/h2>
&lt;p>The Scale Agent stores account data in a dedicated table called &lt;code>clouddriver.kubesvc_accounts&lt;/code>. It does not modify or delete the account data in the original credential source.&lt;/p>
&lt;p>An account has the following lifecycle states:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Non-transient:&lt;/p>
&lt;ul>
&lt;li>&lt;code>INACTIVE&lt;/code>: This is the initial state when a user adds an account. The account is waiting for a migration operation.&lt;/li>
&lt;li>&lt;code>ACTIVE&lt;/code>: Scale Agent watches and manages the account.&lt;/li>
&lt;li>&lt;code>FAILED&lt;/code>: Scale Agent failed to add or delete an account.&lt;/li>
&lt;li>&lt;code>ORPHANED&lt;/code>: Neither Scale Agent nor Clouddriver is managing the account. It is inactive. You usually see this state when restarting or bringing down all of the replicas managing that account.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Transient&lt;/p>
&lt;ul>
&lt;li>&lt;code>TO_MIGRATE&lt;/code>: The account is waiting for migration.&lt;/li>
&lt;li>&lt;code>ACTIVATING&lt;/code>: The account transferred to Scale Agent for activation.&lt;/li>
&lt;li>&lt;code>TO_DEACTIVATE&lt;/code>: Indicates there is an instruction to deactivate the account.&lt;/li>
&lt;li>&lt;code>DEACTIVATING&lt;/code>: A request to stop watching the account has been sent to the Scale Agent.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="manual-account-migration">Manual account migration&lt;/h2>
&lt;p>Migration of an account is the combination of taking the snapshot from a credential source and then activating the accounts.&lt;/p>
&lt;pre class="mermaid">sequenceDiagram
actor User
participant Plugin
participant Service
User-&amp;gt;&amp;gt;Plugin: POST /armory/accounts
Plugin-&amp;gt;&amp;gt;Plugin: Store in clouddriver.kubesvc_accounts
User-&amp;gt;&amp;gt;Plugin: PATCH /armory/accounts
Plugin-&amp;gt;&amp;gt;Service: gRPC AddAccounts
Service--&amp;gt;&amp;gt;Plugin: return
Plugin-&amp;gt;&amp;gt;Plugin: Update status in clouddriver.kubesvc_accounts&lt;/pre>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">POST&lt;/th>
&lt;th style="text-align:left">PATCH&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span> curl --request POST &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --url http://clouddriver:7002/armory/accounts &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --header &lt;span style="color:#f1fa8c">&amp;#39;Content-Type: application/json&amp;#39;&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --data &lt;span style="color:#f1fa8c">&amp;#39;[
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;name&amp;#34;: &amp;#34;account-01&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> },
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;name&amp;#34;: &amp;#34;account-02&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;zoneId&amp;#34;: &amp;#34;agent-1_namespace1&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;kubeconfigFile&amp;#34;: &amp;#34;encryptedFile:k8s!n:kubeconfig!k:config!ns:spinnaker&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> ]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/td>
&lt;td style="text-align:left">&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl --request PATCH &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --url http://localhost:7002/armory/accounts &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --header &lt;span style="color:#f1fa8c">&amp;#39;Content-Type: application/json&amp;#39;&lt;/span> &lt;span style="color:#f1fa8c">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">&lt;/span> --data &lt;span style="color:#f1fa8c">&amp;#39;[
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;name&amp;#34;: &amp;#34;account-01&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;state&amp;#34;: &amp;#34;ACTIVE&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> },
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;name&amp;#34;: &amp;#34;account-02&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;state&amp;#34;: &amp;#34;ACTIVE&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;zoneId&amp;#34;: &amp;#34;agent-1_namespace1&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> &amp;#34;kubeconfigFile&amp;#34;: &amp;#34;encryptedFile:k8s!n:kubeconfig!k:config!ns:spinnaker&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f1fa8c">]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>See &lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/migrate-accounts/"}>Migrate Clouddriver Kubernetes Accounts to the Armory Scale Agent&lt;/a> for detailed instructions and examples.&lt;/p>
&lt;p>&lt;strong>What happens when you initiate a migration request&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>If you &lt;strong>do not&lt;/strong> include a &lt;code>zoneId&lt;/code>, the plugin sends the request to every connected Scale Agent service in an attempt to find one that can process the request. The account&amp;rsquo;s &lt;code>zoneId&lt;/code> is updated to that of the Agent service that is able to process the add request.&lt;/li>
&lt;li>If you &lt;strong>do&lt;/strong> provide a &lt;code>zoneId&lt;/code>, the plugin forwards the request only to matching Agent services.&lt;/li>
&lt;li>Before sending account data to the Agent service, the plugin decrypts the &lt;code>kubeconfig&lt;/code> secret and encodes it in Base64. Then the plugin adds the encoded content as an attribute of the account. The secret data remains encoded in the database; it is not stored in plain text.&lt;/li>
&lt;li>The plugin stores the account data in the &lt;code>clouddriver.kubesvc_accounts&lt;/code> before sending the accounts to the relevant Scale Agent services for processing.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>To reduce overhead, create the &lt;code>kubeconfig&lt;/code> with only the minimum requirements.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;strong>What happens when the service receives a request to add accounts&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>After receiving the set of accounts, the Scale Agent service parses each &lt;code>kubeconfig&lt;/code> and fetches the certificate information from the specified cluster. After the fetch succeeds, the Scale Agent service initiates a process that discovers every Kubernetes kind in the target cluster for initiation of a &lt;a href="https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes">Kubernetes watch&lt;/a>.&lt;/li>
&lt;li>Next, the Scale Agent service creates a new gRPC connection as a response to tell the Scale Agent plugin which accounts are now active. The plugin then updates account data in the &lt;code>clouddriver.kubesvc_accounts&lt;/code> table.&lt;/li>
&lt;/ul>
&lt;p>The plugin does not inform you of the operation results due to potentially long processing time. The more accounts you send, the longer the operation takes to complete. You can check for an ACTIVE account state in the &lt;code>clouddriver.kubesvc_accounts&lt;/code> table by querying the database directly or by calling &lt;code>/agents/kubernetes/accounts/{accountName}&lt;/code>.&lt;/p>
&lt;h2 id="automatic-account-migration">Automatic account migration&lt;/h2>
&lt;blockquote>
&lt;p>This feature requires you to enable &lt;a href="https://spinnaker.io/docs/setup/other_config/accounts/">Clouddriver Account Management&lt;/a> in Spinnaker.&lt;/p>
&lt;/blockquote>
&lt;p>You can configure the Scale Agent to scan for newly created Clouddriver accounts that match a specified pattern and then migrate those accounts to Scale Agent management. This replaces manual requests to migrate and activate accounts.&lt;/p>
&lt;h2 id="clouddriver-account-management-api-request-interception">Clouddriver Account Management API request interception&lt;/h2>
&lt;blockquote>
&lt;p>This feature requires you to enable &lt;a href="https://spinnaker.io/docs/setup/other_config/accounts/">Clouddriver Account Management&lt;/a> in Spinnaker.&lt;/p>
&lt;/blockquote>
&lt;p>The Scale Agent can intercept an account creation requests sent to the &lt;a href="https://spinnaker.io/docs/setup/other_config/accounts/#account-management-api">Cloudddriver Account Management API&lt;/a> &lt;code>POST &amp;lt;GATE_URL&amp;gt;/credentials&lt;/code> endpoint and add those accounts to Scale Agent management.&lt;/p>
&lt;p>The intercept feature provides the following additional functionality:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Account modification&lt;/strong>: When you send an update request to &lt;code>PUT &amp;lt;GATE_URL&amp;gt;/credentials&lt;/code>, the Scale Agent checks to see if the account exists in the &lt;code>clouddriver.kubesvc_accounts&lt;/code> table and if found, updates the account and send the changes to the associated Scale Agent service.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Account deletion&lt;/strong>: When you send a request to &lt;code>DELETE &amp;lt;GATE_URL&amp;gt;/credentials&lt;/code>, the Scale Agent checks to see if the account exists in the &lt;code>clouddriver.kubesvc_accounts&lt;/code> table and if found, deletes the account.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="account-management">Account management&lt;/h2>
&lt;p>Dynamic Accounts provides create, read, update, and delete endpoints for managing accounts stored in &lt;code>clouddriver.kubesvc_accounts&lt;/code>. The following illustrates what happens when you initiate a deletion request.&lt;/p>
&lt;pre class="mermaid">sequenceDiagram
actor User
participant Plugin
participant Service
User-&amp;gt;&amp;gt;Plugin: DELETE /armory/accounts
Plugin-&amp;gt;&amp;gt;Plugin: checks for the account in kubesvc_accounts
Plugin-&amp;gt;&amp;gt;Service: gRPC DeleteAccounts
Service--&amp;gt;&amp;gt;Plugin: return
Plugin-&amp;gt;&amp;gt;Plugin: delete in clouddriver.kubesvc_accounts&lt;/pre>
&lt;p>See &lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/manage-accounts/"}>Manage Kubernetes Accounts in the Armory Scale Agent&lt;/a> for detailed instructions and examples.&lt;/p>
&lt;h2 id="failures-and-retry-mechanism">Failures and retry mechanism&lt;/h2>
&lt;p>If the Scale Agent cannot add an account, it updates the account state to FAILED in the &lt;code>clouddriver.kubesvc_accounts&lt;/code> table. You can find the reason in the &lt;code>error_message&lt;/code> column and the number of attempts in the &lt;code>failed_count&lt;/code> column.&lt;/p>
&lt;p>The Scale Agent plugin has an automatic retry mechanism for FAILED accounts. You can configure the max retries and the frequency of retries by setting &lt;code>kubesvc.dynamicAccounts.retryFrequencySeconds&lt;/code> (default: 5) and &lt;code>kubesvc.dynamicAccounts.maxRetries&lt;/code> (default: 3) in the plugin configuration.&lt;/p>
&lt;p>If an account is manually patched to ACTIVE using the API, the &lt;code>failed_count&lt;/code> resets and the retries can start over.&lt;/p>
&lt;h2 id="automatic-recovery-of-orphaned-accounts">Automatic recovery of orphaned accounts&lt;/h2>
&lt;p>When all of the Scale Agent services managing a specific account die, the account goes into an ORPHANED state. The account state changes back to ACTIVE the next time the managing Scale Agent service becomes active. The same happens when a new replica is scaled up for an ACTIVE account. That way consistency is maintained across replicas.&lt;/p>
&lt;h2 id="whats-next">What&amp;rsquo;s next&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/enable/"}>Enable and Configure Dynamic Accounts in the Armory Scale Agent&lt;/a>&lt;/li>
&lt;li>&lt;a href="/plugins/scale-agent/tasks/dynamic-accounts/migrate-accounts/"}>Migrate Clouddriver Kubernetes Accounts to the Armory Scale Agent&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Plugins: Kubernetes Permissions for the Armory Scale Agent</title><link>/plugins/scale-agent/concepts/service-permissions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/plugins/scale-agent/concepts/service-permissions/</guid><description>
&lt;h2 id="permissions">Permissions&lt;/h2>
&lt;p>The Scale Agent service can use a &lt;code>kubeconfig&lt;/code> file loaded as a Kubernetes secret when deploying to a remote cluster. Also, you can configure Agent permissions using a Kubernetes Service Account when deploying to the cluster the Armory Scale Agent resides in.&lt;/p>
&lt;p>The Scale Agent service should have &lt;code>ClusterRole&lt;/code> authorization if you need to deploy pods across your cluster or &lt;code>Role&lt;/code> authorization if you deploy pods only to a single namespace.&lt;/p>
&lt;ul>
&lt;li>If Scale Agent service is running in &lt;a href="/plugins/scale-agent/#agent-mode">Agent Mode&lt;/a>, then the &lt;code>ClusterRole&lt;/code> or &lt;code>Role&lt;/code> is the one attached to the Kubernetes Service Account mounted by the Armory Scale Agent pod.&lt;/li>
&lt;li>If Scale Agent service is running in any of the other modes, then the &lt;code>ClusterRole&lt;/code> or &lt;code>Role&lt;/code> is the one the &lt;code>kubeconfigFile&lt;/code> uses to interact with the target cluster. &lt;code>kubeconfigFile&lt;/code> is configured in &lt;code>armory-agent.yml&lt;/code> of the Armory Scale Agent pod.&lt;/li>
&lt;/ul>
&lt;p>Example configuration for deploying &lt;code>Pod&lt;/code> manifests:&lt;/p>
&lt;ul class="nav nav-tabs justify-content-end" id="tabs-1" role="tablist">
&lt;li class="nav-item">
&lt;button class="nav-link active"
id="tabs-01-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-00" role="tab"
aria-controls="tabs-01-00" aria-selected="true">
ClusterRole
&lt;/button>
&lt;/li>&lt;li class="nav-item">
&lt;button class="nav-link"
id="tabs-01-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-01" role="tab"
aria-controls="tabs-01-01" aria-selected="false">
Role
&lt;/button>
&lt;/li>
&lt;/ul>
&lt;div class="tab-content" id="tabs-1-content">
&lt;div class="tab-body tab-pane fade show active"
id="tabs-01-00" role="tabpanel" aria-labelled-by="tabs-01-00-tab" tabindex="1">
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: ClusterRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: agent-role
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">rules&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ff79c6">apiGroups&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">resources&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - pods
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - pods/log
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - pods/finalizers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">verbs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - get
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - watch
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - create
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - patch
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - delete
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>
&lt;div class="tab-body tab-pane fade"
id="tabs-01-01" role="tabpanel" aria-labelled-by="tabs-01-01-tab" tabindex="1">
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">kind&lt;/span>: Role
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">name&lt;/span>: agent-role
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ff79c6">rules&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#ff79c6">apiGroups&lt;/span>: &lt;span style="color:#f1fa8c">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">resources&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - pods
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - pods/log
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - pods/finalizers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ff79c6">verbs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - get
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - watch
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - create
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - patch
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - delete
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>
&lt;/div>
&lt;p>See the Kubernetes &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/">Using RBAC Authorization&lt;/a> guide for details on configuring &lt;code>ClusterRole&lt;/code> and &lt;code>Role&lt;/code> authorization.&lt;/p></description></item></channel></rss>