---
# System prepended metadata

title: Approval Deployment 2020-04-14

---

# Approval Deployment 2020-04-14

## 0. Goal

- CIDR Change
    - `10.x` -> `100.x`
- EC2 Instance Type Change
    - `r5d.2xlarge` -> `m5d.4xlarge`
- Flux Workaround
- Autoscaler Update to handle mutliple AZ properly
- Metrics-Server to bring kubectl top po back
- AMI Image Update


## 0.1 Document Current State

Note current state of Pods in `default` and `ingress` NS, so we know what has been running and what not :)

```bash
kubectl -n ingress get po > get_po_ingress
kubectl -n default get po > get_po_default
```

## 1. Stop cluster-autoscaler (scale to 0)

**Note:** Lets scale down both Cluster-Autoscalers and fix them after Node/ASG-Operations

```bash
kubectl -n kube-system delete deploy cluster-autoscaler
kubectl -n kube-system scale deploy/cluster-autoscaler-aws-cluster-autoscaler --replicas=0

kubectl -n kube-system get deploy | grep autoscaler
```

Stop alert-manager to stop sending alerts for the time of deployment

```bash
kubectl -n monitoring scale <tbd>

```

## 2. Rollout Weavenet Patch

Rollout patch and wait until it is distributed accross all nodes

```bash
# Patch weave-net DaemonSet
cat <<EOF | kubectl patch ds weave-net -n kube-system --patch "$(cat -)"
spec:
  template:
    spec:
      containers:
      - name: weave
        image: weaveworks/weave-kube:2.6.0
        env:
        - name: IPALLOC_RANGE
          value: 100.96.0.0/11
        - name: WEAVE_MTU
          value: "8912"
      - name: weave-npc
        image: weaveworks/weave-npc:2.6.0
EOF
```

Check if DS is distributed in whole Cluster

```bash
kubectl -n kube-system get ds weave-net
```

## 3. Cordon all nodes to distinguish old and new ones

This should mark all nodes (except masters) as "SchedulingDisabled".

For easier later reference, store the "old_nodes" :)

```bash
kubectl get nodes --no-headers -owide > old_nodes
```

Cordon all nodes except "master":

```bash
kubectl get nodes --no-headers -owide | grep -v "master" | awk '{print$1}' | while read name ;
do
     echo "Cordoning $name";
     kubectl cordon "$name"
done 2>/dev/null
```

## 4. `Kops update` to update Instance Groups and Launch-Configurations

- this can be done by triggering "[Deploy-K8S](https://ci-plt.pre.eu.dp.vwg-connect.com/teams/dp-corebe-approval/pipelines/dp-corebe-kubernetes-approval/jobs/deploy-k8s/builds/16)" Job
- **IMPORTANT** the Job should be interrupted after all three Master Nodes are exchanged
    - For this purpose a tag [`1.5.27-20200408-double-asgs`](https://devstack.vwgroup.com/bitbucket/projects/MLSS/repos/w-025-execution-environment/commits?until=refs%2Ftags%2F1.5.27-20200408-double-asgs) has been created that can/should be used!
    - This tag will double ASG Capacities

* This will Update the Kops Cluster Configuration (and therefore the Launch Configs of the ASGs) AND update our Master Nodes as desired.
* All amount of Nodes in remaining ASGs should be doubled (new Nodes will start to boot)

### The result of this Step should be:

- All Launch Configs are Up-To-Date
- Master Nodes with new Launch Configs
- All ASGs have the double amount of Nodes
    - this means in our ASGs we have now "old" and "new" nodes

## 5. Drain all cordoned nodes

```bash
kubectl get nodes --no-headers -owide | grep -v "master" | grep "SchedulingDisabled" | awk '{print$1}' | while read name ;
do
    echo "Draining $name";
    kubectl drain --ignore-daemonsets --grace-period=300 --force $name
done 2>/dev/null
```

To be considered to make sure all workloads are actually rescheduled:

```bash
kubectl drain --ignore-daemonsets --grace-period=300 --delete-local-data --force $name
```

> This filter checks if `emptyDir` exists for a pod or not. If the pod uses `emptyDir` to store local data, it may not be safe to delete because if a pod is removed from a node the data in the `emptyDir` is deleted with it. Just like with the unreplicated filter, it is up for the implementation to decide what to do with these pods. `drain` provides a switch for this as well; if `--delete-local-data` is set, `drain` will proceed even if there are pods using the `emptyDir` and will delete the pods and therefore delete the local data as well.
> 
> *Source: https://banzaicloud.com/blog/drain/*
> Interesting Issue about it: https://github.com/kubernetes/kubernetes/issues/80228

## 6. Shutdown all drained and cordoned nodes

After shutting them down, they will reboot with the new Launch Configuration

**Note:** as we still have our `systemd-resolved` issue, it is wise to check the current node count and compare it afterwards!

```bash
kubectl get nodes --no-headers | wc -l
```

Shutdown all Nodes

```bash
kubectl get nodes --no-headers -owide | grep -v "master" | grep "SchedulingDisabled" | awk '{print$6}' | while read ip ;
do
    echo "Shutting down $ip";
    # Cpmmented out for accidentally Copy/Pasting
    # sudo -i ssh -o StrictHostKeyChecking=no -n ubuntu@$ip sudo -i shutdown now
done 2>/dev/null
```

## 7. Let the whole "Deploy-K8S" Job run

- **configure the actual tag ` 1.5.27-20200408`!**
- should be way faster, as it doesn't mess with ASGs anymore
    - this will set the min/max values back; NOT the desired once!
- necessary to deploy Flux
- necessary to deploy new Autoscaler Version

## 8. Set cluster-autoscaler to 1

The Cluster-Autoscaler will probably be set to 1 by the step 7.


Ensure, that the cluster-autoscaler is actually taking down remaining nodes! This will take ~10min until the first instances will be removed

–	reduce capacity of all ASGs back to normal
–	let cluster-autoscaler do the work!

```bash
kubectl -n kube-system scale deploy/cluster-autoscaler-aws-cluster-autoscaler --replicas=1
```