github.com/GoogleContainerTools/skaffold/v2@v2.13.2/docs-v2/content/en/docs/workflows/handling-platforms.md (about)

     1  ---
     2  title: "Managing ARM workloads [NEW]"
     3  linkTitle: "Managing ARM workloads [NEW]"
     4  featureId: build.platforms
     5  weight: 50
     6  ---
     7  
     8  Skaffold has a lot of intelligence built-in to simplify working with ARM workloads. Whether developing on an Apple Silicon Macbook that uses an ARM based chip, or deploying to a GKE Kubernetes cluster having ARM nodes, Skaffold can take away the complexities that arise when the architecture of your development machine and Kubernetes cluster don't match.
     9  
    10  ## Why is image architecture important?
    11  
    12  Container images are built targeting specific [Instruction Set Architectures](https://en.wikipedia.org/wiki/Instruction_set_architecture) like `amd64`, `arm64`, etc. **You must use container images that are compatible with the architecture of the node where you intend to run the workloads.** For example, to deploy to a GKE cluster running ARM nodes, the image needs to be built for `linux/arm64` platform.
    13  
    14  All image builders build for different default architecture and not all support cross-architecture builds. For instance [Docker]({{<relref "/docs/builders/builder-types/docker">}}) will build the image for the same architecture as the host machine, whereas [Buildpacks]({{<relref "/docs/builders/builder-types/buildpacks">}}) will always build it for `amd64`.
    15  
    16  Additionally, the following combination of development machine and cluster node architectures can make it difficult to build and deploy images correctly:
    17  
    18  * Dev machine architecture is `amd64` while the target cluster runs `arm64` nodes.
    19  * Dev machine architecture is `arm64` (say Apple Silicon Macbooks) while the target cluster runs `amd64` nodes.
    20  * The target cluster runs both `arm64` and `amd64` nodes (mixed node pools).
    21  
    22  🎉 *Skaffold provides an opionated way to handle all these cases effectively.* 🎉
    23  
    24  ## Skaffold can set the image architecture automatically
    25  
    26  When running Skaffold in an interactive mode like `skaffold dev`, `skaffold debug` or `skaffold run` where the intention is to build an image from the application code, and immediately deploy it to a Kubernetes cluster, Skaffold will check the active Kubernetes cluster node architecture and provide that as an argument to the respective image builder. If the cluster has multiple architecture nodes, then Skaffold will also create appropriate Kubernetes [`affinity`](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) rules so that the Kubernetes Pods with these images are assigned to matching architecture nodes.
    27  
    28  {{< alert title="Note" >}}
    29  Skaffold will create platform node `affinity` rules only for clusters having multiple architecture nodes. You can also force this using the flag `--enable-platform-node-affinity=true` to always create these affinity rules in the Kubernetes manifests for built images.
    30  {{< /alert >}}
    31  
    32  Let's test this in a [sample Golang](https://github.com/GoogleContainerTools/skaffold/tree/main/examples/cross-platform-builds) project:
    33  
    34  * The `skaffold.yaml` file defines a single [Docker build artifact](https://github.com/GoogleContainerTools/skaffold/blob/main/examples/cross-platform-builds/Dockerfile) and deploys it in a [`Kubernetes Pod`](https://github.com/GoogleContainerTools/skaffold/blob/main/examples/cross-platform-builds/k8s-pod.yaml).
    35  
    36  * First set the active Kubernetes context to a cluster having only `linux/amd64` nodes, and run:
    37  
    38    ```cmd
    39    skaffold dev --default-repo=your/container/registy
    40    ```
    41  
    42    Skaffold will detect the cluster node platform `linux/amd64` and build the image for this platform:
    43  
    44    ```cmd
    45    skaffold dev --default-repo=gcr.io/k8s-skaffold
    46    Listing files to watch...
    47    - skaffold-example
    48    Generating tags...
    49    - skaffold-example -> gcr.io/k8s-skaffold/skaffold-example:latest
    50    Starting build...
    51    Building [skaffold-example]...
    52    Target platforms: [linux/amd64]
    53    ...
    54    Build [skaffold-example] succeeded
    55    Starting deploy...
    56    - pod/getting-started created
    57    Waiting for deployments to stabilize...
    58    - pods is ready.
    59    Deployments stabilized in 7.42 seconds
    60    Press Ctrl+C to exit
    61    Watching for changes...
    62    [getting-started] Hello world! Running on linux/amd64
    63    ```
    64  
    65  * Now set the active Kubernetes context to a cluster containing only `linux/arm64` nodes. See [here](https://cloud.google.com/kubernetes-engine/docs/how-to/prepare-arm-workloads-for-deployment) to know how you can create an ARM GKE cluster.
    66  
    67    Re-running the `dev` command will now build a `linux/arm64` image.
    68  
    69    ```cmd
    70    skaffold dev --default-repo=gcr.io/k8s-skaffold
    71    ...
    72    ...
    73    [getting-started] Hello world! Running on linux/arm64
    74    ```
    75  
    76  * Now set the active Kubernetes context to a cluster containing both `linux/arm64` and `linux/amd64` nodes. You can create a GKE cluster with 2 node pools, one having `linux/amd64` nodes, and the other having `linux/arm64` nodes.
    77  
    78    Re-run the `dev` command but with an explicit platform target this time via the `--platform` flag. If we don't provide the target platform explicitly then Skaffold will choose one between `linux/amd64` and `linux/arm64`, trying to match your local dev machine architecture.
    79  
    80    ```cmd
    81    skaffold dev --default-repo=your/container/registy --platform=linux/amd64
    82    ```
    83  
    84    Skaffold will build a `linux/amd64` image and insert a `nodeAffinity` definition to the `Pod` so that it gets scheduled on the matching architecture node.
    85  
    86    ```cmd
    87    skaffold dev --default-repo=gcr.io/k8s-skaffold --platform=linux/amd64
    88    ...
    89    ...
    90    [getting-started] Hello world! Running on linux/amd64
    91    ```
    92  
    93  * Validate that the `nodeAffinity` was applied by running the command (skip `| jq` if you don't have `jq` installed):
    94  
    95    ```cmd
    96    kubectl get pod getting-started  -o=jsonpath='{.spec.affinity}' | jq
    97    {
    98      "nodeAffinity": {
    99        "requiredDuringSchedulingIgnoredDuringExecution": {
   100          "nodeSelectorTerms": [
   101            {
   102              "matchExpressions": [
   103                {
   104                  "key": "kubernetes.io/os",
   105                  "operator": "In",
   106                  "values": [
   107                    "linux"
   108                  ]
   109                },
   110                {
   111                  "key": "kubernetes.io/arch",
   112                  "operator": "In",
   113                  "values": [
   114                    "amd64"
   115                  ]
   116                }
   117              ]
   118            }
   119          ]
   120        }
   121      }
   122    }
   123    ```
   124  
   125  This example will run the same whether you're using an `arm64` machine (say an Apple Silicon Macbook) or an `amd64` machine.
   126  
   127  Skaffold also supports cross-architecture builds on [Google Cloud Build](https://cloud.google.com/build). You can rerun this example, with the additional flag `--profile cloudbuild` to all the `dev` commands to build on `Google Cloud Build` instead of the local Docker daemon.
   128  
   129  ## What about multi-arch images?
   130  
   131  A [multi-arch image](https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/) is an image that can support multiple architectures. It looks like a single image with a single tag, but is actually a list of images targeting multiple architectures organized by an [image index](https://github.com/opencontainers/image-spec/blob/main/image-index.md). When you deploy a multi-arch image to a cluster, the container runtime automatically chooses the right image that is compatible with the architecture of the node to which it is being deployed. This simplifies targeting multiple clusters of different architecture nodes, and/or mixed-architecture nodes.
   132  
   133  Skaffold supports building multi-platform images natively using the [jib builder]({{<relref "/docs/builders/builder-types/jib" >}}), the [ko builder]({{<relref "/docs/builders/builder-types/ko">}}) and the [custom builder]({{<relref "/docs/builders/builder-types/custom" >}}). For other builders that support building cross-architecture images, Skaffold will iteratively build a single platform image for each target architecture and stitch them together into a multi-platform image, and push it to the registry.
   134  
   135  ![multi-arch-flow](/images/multi-arch-flow.png)
   136  
   137  Let's test this in the same [sample Golang](https://github.com/GoogleContainerTools/skaffold/tree/main/examples/cross-platform-builds) project as before:
   138  
   139  * Run this command to build for the target architectures `linux/amd64` and `linux/arm64`:
   140  
   141    ```cmd
   142    skaffold build -t latest --default-repo=your/container/registy --platform=linux/amd64,linux/arm64
   143    ...
   144    Building [skaffold-example]...
   145    Target platforms: [linux/amd64,linux/arm64]
   146    ...
   147    [+] Building 0.3s (13/13) FINISHED
   148    ...
   149    => => writing image sha256:10af3142e460566f5791c48758f0040cef6932cbcb0766082dcbb0d8db7653e7
   150    => => naming to gcr.io/k8s-skaffold/skaffold-example:latest_linux_amd64
   151    ...
   152    latest_linux_amd64: digest: sha256:15bd4f2380e99b3563f8add1aba9691e414d4cc5701363d9c74960a20fb276c4 size: 739
   153    ...
   154    [+] Building 52.8s (13/13) FINISHED
   155    ...
   156    => => writing image sha256:68866691e2d6f079b116e097ae4e67a53eaf89e825b52d6f31f2e9cc566974de
   157    => => naming to gcr.io/k8s-skaffold/skaffold-example:latest_linux_arm64
   158    ...
   159    4e0c2525c370: Pushed
   160    latest_linux_arm64: digest: sha256:868d0aec1cc7d2ed1fa1e840f38ff1aa50c3cc3d3232ea17a065618eaec4e82b size: 739
   161    Build [skaffold-example] succeeded
   162    ```
   163  
   164  * Validate that the image just built was multi-arch, by running the following `docker` command:
   165  
   166    ```cmd
   167    docker manifest inspect your/container/registry/skaffold-example:latest | grep -A 3 "platform"
   168    ```
   169  
   170    Outputs:
   171  
   172    ```cmd
   173      "platform": {
   174          "architecture": "amd64",
   175          "os": "linux"
   176      }
   177    --
   178      "platform": {
   179          "architecture": "arm64",
   180          "os": "linux"
   181      }
   182    ```
   183  
   184  * Now if we render the Kubernetes Pod manifest for this multi-arch image, then it'll have platform affinity definition targeting both `linux/amd64` and `linux/arm64` architectures.
   185  
   186    ```cmd
   187    skaffold render --default-repo=your/container/registry --enable-platform-node-affinity
   188    ```
   189    
   190    Outputs:
   191  
   192    ```cmd
   193    apiVersion: v1
   194    kind: Pod
   195    metadata:
   196      name: getting-started
   197      namespace: default
   198    spec:
   199      affinity:
   200        nodeAffinity:
   201          requiredDuringSchedulingIgnoredDuringExecution:
   202            nodeSelectorTerms:
   203            - matchExpressions:
   204              - key: kubernetes.io/os
   205                operator: In
   206                values:
   207                - linux
   208              - key: kubernetes.io/arch
   209                operator: In
   210                values:
   211                - amd64
   212            - matchExpressions:
   213              - key: kubernetes.io/os
   214                operator: In
   215                values:
   216                - linux
   217              - key: kubernetes.io/arch
   218                operator: In
   219                values:
   220                - arm64
   221      containers:
   222      - image: gcr.io/k8s-skaffold/skaffold-example:latest@sha256:9ecf4e52f7ff64b35deacf9d6eedc03f35d69e0b4bf3679b97ba492f4389f784
   223        name: getting-started
   224    ```
   225  
   226  {{< alert title="Note" >}}
   227  
   228  * Multi-arch images need to be pushed to a container registry, as the local Docker deamon doesn't yet support storing multi-arch images.
   229  
   230  * For interactive modes like `skaffold dev` and `skaffold debug` requiring fast and repeated `build-render-deploy` iterations, Skaffold will choose only one build architecture and build a single-platform image, even if you specify multiple target platforms.
   231  
   232  * If you need to build a multi-arch image with an interactive mode then use `skaffold run`. This will build the multi-arch image and deploy it to the active Kubernetes cluster.
   233  {{< /alert >}}