# Fleet Updates

> Common patterns and approaches for updating Fleets with newer and/or different versions of your `GameServer` configuration.

---

LLMS index: [llms.txt](/site/llms.txt)

---

## Rolling Update Strategy

When Fleets are edited and updated, the default strategy of Agones is to roll the new version of the `GameServer`
out to the entire `Fleet`, in a step by step increment and decrement by adding a chunk of the new version and removing
a chunk of the current set of `GameServers`.

This is done while ensuring that `Allocated` `GameServers` are not deleted
until they are specifically shutdown through the game servers SDK, as they are expected to have players on them.

You can see this in the `Fleet.Spec.Strategy` [reference](/site/docs/reference/fleet/), with controls for how
much of the `Fleet` is  incremented and decremented at one time:

```yaml
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
```

So when a Fleet is edited (any field other than `replicas`, see note below), either through `kubectl` `edit`/`apply` or via the Kubernetes API, this performs the following operations:

1. Adds the `maxSurge` number of `GameServers` to the Fleet.
1. Shutdown the `maxUnavailable` number of `GameServers` in the Fleet, skipping `Allocated` `GameServers`.
1. Repeat above steps until all the previous `GameServer` configurations have been `Shutdown` and deleted.

By default, a Fleet will wait for new `GameServers` to become `Ready` during a Rolling Update before continuing to shutdown additional `GameServers`, only counting `GameServers` that are `Ready` as being available when calculating the current `maxUnavailable` value which controls the rate at which `GameServers` are updated.
This ensures that a Fleet cannot accidentally have zero `GameServers` in the `Ready` state if something goes wrong during a Rolling Update or if `GameServers` have a long delay before moving to the `Ready` state.

<div class="alert alert-info" role="alert"><div class="h4 alert-heading" role="heading">Note</div>


When `Fleet` update contains only changes to the `replicas` parameter, then new GameServers will be created/deleted straight away,
which means in that case `maxSurge` and `maxUnavailable` parameters for a RollingUpdate will not be used.
The RollingUpdate strategy takes place when you update `spec` parameters other than `replicas`.

If you are using a Fleet which is scaled by a FleetAutoscaler, [read the Fleetautoscaler guide](/site/docs/getting-started/create-fleetautoscaler/#7-change-autoscaling-parameters) for more details on how RollingUpdates with FleetAutoscalers need to be implemented.

You could also check the behaviour of the Fleet with a RollingUpdate strategy on a test `Fleet` to preview your upcoming updates.
Use `kubectl describe fleet` to track scaling events in a Fleet.
</div>


## Recreate Strategy

This is an optimal `Fleet` update strategy if you want to replace all `GameServers` that are not `Allocated`
with a new version as quickly as possible.

You can see this in the `Fleet.Spec.Strategy` [reference](/site/docs/reference/fleet/):

```yaml
  strategy:
    type: Recreate
```

So when a Fleet is edited, either through `kubectl` `edit`/`apply` or via the Kubernetes API, this performs the following operations:

1. `Shutdown` all `GameServers` in the Fleet that are not currently `Allocated`.
1. Create the same number of the new version of the `GameServers` that were previously deleted.
1. Repeat above steps until all the previous `GameServer` configurations have been `Shutdown` and deleted.

## Two (or more) Fleets Strategy

If you want very fine-grained control over the rate that new versions of a `GameServer` configuration is rolled out, or
if you want to do some version of A/B testing or smoke test between different versions, running two (or more) `Fleets` at the same time is a
good solution for this.

To do this, create a second `Fleet` inside your cluster, starting with zero replicas. From there you can scale this newer `Fleet`
up and the older `Fleet` down as required by your specific rollout strategy.

This also allows you to rollback if issues arise with the newer version, as you can delete the newer `Fleet`
and scale up the old Fleet to its previous levels, resulting in minimal impact to the players.

<div class="alert alert-info" role="alert"><div class="h4 alert-heading" role="heading">Note</div>


For GameServerAllocation, you will need to have at least a single shared label between the `GameServers` in each
Fleet.
</div>


### GameServerAllocation Across Fleets

Since `GameServerAllocation` is powered by label selectors, it is possible to allocate across multiple fleets, and/or
give preference to particular sets of `GameServers` over others. You can see details of this in
the `GameServerAllocation` [reference](/site/docs/reference/gameserverallocation/).

In a scenario where a new `v2` version of a `Fleet` is being slowly scaled up in a separate Fleet from the previous `v1`
Fleet, we can specify that we `prefer` allocation to occur from the `v2` Fleet, and if none are available, fallback to
the `v1` Fleet, like so:



  
  
<ul class="nav nav-tabs" id="tabs-5" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-05-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-00" role="tab"
          data-td-tp-persist="selectors" aria-controls="tabs-05-00" aria-selected="true">
        selectors
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-05-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-01" role="tab"
          data-td-tp-persist="required & preferred (deprecated)" aria-controls="tabs-05-01" aria-selected="false">
        required &amp; preferred (deprecated)
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-5-content">
    <div class="tab-pane fade show active"
        id="tabs-05-00" role="tabpanel" aria-labelled-by="tabs-05-00-tab" tabindex="5">
        <div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#4e9a06">&#34;allocation.agones.dev/v1&#34;</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#000">GameServerAllocation</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span><span style="color:#204a87;font-weight:bold">selectors</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">    </span>- <span style="color:#204a87;font-weight:bold">matchLabels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">        </span><span style="color:#204a87;font-weight:bold">agones.dev/fleet</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#000">v2</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">    </span>- <span style="color:#204a87;font-weight:bold">matchLabels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">        </span><span style="color:#204a87;font-weight:bold">game</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#000">my-awesome-game</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span></span></span></code></pre></div>
    </div>
    <div class="tab-pane fade"
        id="tabs-05-01" role="tabpanel" aria-labelled-by="tabs-05-01-tab" tabindex="5">
        <div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#4e9a06">&#34;allocation.agones.dev/v1&#34;</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#000">GameServerAllocation</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span><span style="color:#8f5902;font-style:italic"># Deprecated, use field selectors instead.</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span><span style="color:#204a87;font-weight:bold">required</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">    </span><span style="color:#204a87;font-weight:bold">matchLabels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">      </span><span style="color:#204a87;font-weight:bold">game</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#000">my-awesome-game</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span><span style="color:#8f5902;font-style:italic"># Deprecated, use field selectors instead.</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span><span style="color:#204a87;font-weight:bold">preferred</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">    </span>- <span style="color:#204a87;font-weight:bold">matchLabels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">        </span><span style="color:#204a87;font-weight:bold">agones.dev/fleet</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8"> </span><span style="color:#000">v2</span><span style="color:#f8f8f8">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8">  </span></span></span></code></pre></div>
    </div>
</div>


In this example, all `GameServers` have the label `game: my-awesome-game`, so the Allocation will search across both
Fleets through that mechanism. The `selectors` label matching selector tells the allocation system to first search
all `GameServers` with the `v2` `Fleet` label, and if not found, search through the rest of the set.

The above `GameServerAllocation` can then be used while you scale up the `v2` Fleet and scale down the original Fleet at
the rate that you deem fit for your specific rollout.

## Notifying GameServers on Fleet Update/Downscale


When `Allocated` `GameServers` are utilised for a long time, such as a Lobby `GameServer`,
or a `GameServer` that is being reused multiple times in a row, it can be useful
to notify an `Allocated` `GameServer` process when its backing Fleet has been updated.
When an update occurs, the `Allocated` `GameServer`, may want to actively perform a graceful shutdown and release its
resources such that it can be replaced by a new version, or similar actions.

To do this, we provide the ability to apply a user-provided set of labels and/or annotations to the `Allocated`
`GameServers` when a `Fleet` update occurs that updates its `GameServer` template, or generally
causes the `Fleet` replica count to drop below the number of currently `Allocated` `GameServers`.

This provides two useful capabilities:

1. The `GameServer` [`SDK.WatchGameServer()`](/site/docs/guides/client-sdks/#watchgameserverfunctiongameserver)
   command can be utilised to react to this annotation and/or label change to
   indicate the Fleet system change, and the game server binary could execute code accordingly.
2. This can also be used to proactively update `GameServer` labels, to effect change in allocation strategy - such as
   preferring the newer `GameServers` when allocating, but falling back to the older version if there aren't enough
   of the new ones yet spun up.

The labels and/or annotations are applied to `GameServers` in a `Fleet` in the order designated by their configured [Fleet scheduling](/site/docs/advanced/scheduling-and-autoscaling/#fleet-scheduling).

Example yaml configuration:

```yaml
apiVersion: "agones.dev/v1"
kind: Fleet
metadata:
  name: simple-game-server
spec:
  replicas: 2
  allocationOverflow: # This specifies which annotations and/or labels are applied
    labels:
      mykey: myvalue
      version: "" # empty an existing label value, so it's no longer in the allocation selection
    annotations:
      event: overflow
  template:
    spec:
      ports:
        - name: default
          containerPort: 7654
      template:
        spec:
          containers:
            - name: simple-game-server
              image: us-docker.pkg.dev/agones-images/examples/simple-game-server:0.27
```

See the [Fleet reference](/site/docs/reference/fleet/) for more details.


<!-- This is the only way I could get the alert to work in a feature code -->
<div class="alert alert-info" role="alert"><div class="h4 alert-heading" role="heading">Note</div>

This works the same across Fleet resizing and Rolling/Recreate Updates, in that the implementation responds to the
underlying `GameServerSet`'s replicas being shrunk to a value smaller than the number of `Allocated`
`GameServers` it controls. Therefore, this functionality works equally well with a rolling update as it does with an
update strategy that requires at least two `Fleets`.
</div>
