sigs.k8s.io/cluster-api@v1.7.1/docs/book/src/developer/tilt.md (about)

     1  # Developing Cluster API with Tilt
     2  
     3  ## Overview
     4  
     5  This document describes how to use [kind](https://kind.sigs.k8s.io) and [Tilt](https://tilt.dev) for a simplified
     6  workflow that offers easy deployments and rapid iterative builds.
     7  
     8  ## Prerequisites
     9  
    10  1. [Docker](https://docs.docker.com/install/): v19.03 or newer
    11  2. [kind](https://kind.sigs.k8s.io): v0.22.0 or newer
    12  3. [Tilt](https://docs.tilt.dev/install.html): v0.30.8 or newer
    13  4. [kustomize](https://github.com/kubernetes-sigs/kustomize): provided via `make kustomize`
    14  5. [envsubst](https://github.com/drone/envsubst): provided via `make envsubst`
    15  6. [helm](https://github.com/helm/helm): v3.7.1 or newer
    16  7. Clone the [Cluster API](https://github.com/kubernetes-sigs/cluster-api) repository
    17     locally
    18  8. Clone the provider(s) you want to deploy locally as well
    19  
    20  ## Getting started
    21  
    22  ### Create a kind cluster
    23  A script to create a KIND cluster along with a local Docker registry and the correct mounts to run CAPD is included in the hack/ folder.
    24  
    25  To create a pre-configured cluster run:
    26  
    27  ```bash
    28  ./hack/kind-install-for-capd.sh
    29  ```
    30  
    31  You can see the status of the cluster with:
    32  
    33  ```bash
    34  kubectl cluster-info --context kind-capi-test
    35  ```
    36  
    37  ### Create a tilt-settings file
    38  
    39  Next, create a `tilt-settings.yaml` file and place it in your local copy of `cluster-api`. Here is an example that uses the components from the CAPI repo:
    40  
    41  ```yaml
    42  default_registry: gcr.io/your-project-name-here
    43  enable_providers:
    44  - docker
    45  - kubeadm-bootstrap
    46  - kubeadm-control-plane
    47  ```
    48  
    49  To use tilt to launch a provider with its own repo, using Cluster API Provider AWS here, `tilt-settings.yaml` should look like: 
    50  
    51  ```yaml
    52  default_registry: gcr.io/your-project-name-here
    53  provider_repos:
    54  - ../cluster-api-provider-aws
    55  enable_providers:
    56  - aws
    57  - kubeadm-bootstrap
    58  - kubeadm-control-plane
    59  ```
    60  
    61  <aside class="note">
    62  
    63  If you prefer JSON, you can create a `tilt-settings.json` file instead. YAML will be preferred if both files are present.
    64  
    65  </aside>
    66  
    67  #### tilt-settings fields
    68  
    69  **allowed_contexts** (Array, default=[]): A list of kubeconfig contexts Tilt is allowed to use. See the Tilt documentation on
    70  [allow_k8s_contexts](https://docs.tilt.dev/api.html#api.allow_k8s_contexts) for more details.
    71  
    72  **default_registry** (String, default=[]): The image registry to use if you need to push images. See the [Tilt
    73  documentation](https://docs.tilt.dev/api.html#api.default_registry) for more details.
    74  Please note that, in case you are not using a local registry, this value is required; additionally, the Cluster API
    75  Tiltfile protects you from accidental push on `gcr.io/k8s-staging-cluster-api`.
    76  
    77  **build_engine** (String, default="docker"): The engine used to build images. Can either be `docker` or `podman`.
    78  NB: the default is dynamic and will be "podman" if the string "Podman Engine" is found in `docker version` (or in `podman version` if the command fails).
    79  
    80  **kind_cluster_name** (String, default="capi-test"): The name of the kind cluster to use when preloading images.
    81  
    82  **provider_repos** (Array[]String, default=[]): A list of paths to all the providers you want to use. Each provider must have a
    83  `tilt-provider.yaml` or `tilt-provider.json` file describing how to build the provider.
    84  
    85  **enable_providers** (Array[]String, default=['docker']): A list of the providers to enable. See [available providers](#available-providers)
    86  for more details.
    87  
    88  **template_dirs** (Map{String: Array[]String}, default={"docker": [
    89  "./test/infrastructure/docker/templates"]}): A map of providers to directories containing cluster templates. An example of the field is given below. See [Deploying a workload cluster](#deploying-a-workload-cluster) for how this is used.
    90  
    91  ```yaml
    92  template_dirs:
    93    docker:
    94    - ./test/infrastructure/docker/templates
    95    - <other-template-dir>
    96    azure:
    97    - <azure-template-dir>
    98    aws:
    99    - <aws-template-dir>
   100    gcp:
   101    - <gcp-template-dir>
   102  ```
   103  
   104  **kustomize_substitutions** (Map{String: String}, default={}): An optional map of substitutions for `${}`-style placeholders in the
   105  provider's yaml. These substitutions are also used when deploying cluster templates. See [Deploying a workload cluster](#deploying-a-workload-cluster).
   106  
   107  **Note**: When running E2E tests locally using an existing cluster managed by Tilt, the following substitutions are required for successful tests:
   108  ```yaml
   109  kustomize_substitutions:
   110    CLUSTER_TOPOLOGY: "true"
   111    EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true"
   112    EXP_RUNTIME_SDK: "true"
   113    EXP_MACHINE_SET_PREFLIGHT_CHECKS: "true"
   114  ```
   115  
   116  {{#tabs name:"tab-tilt-kustomize-substitution" tabs:"AWS,Azure,DigitalOcean,GCP,vSphere"}}
   117  {{#tab AWS}}
   118  
   119  For example, if the yaml contains `${AWS_B64ENCODED_CREDENTIALS}`, you could do the following:
   120  
   121  ```yaml
   122  kustomize_substitutions:
   123    AWS_B64ENCODED_CREDENTIALS: "your credentials here"
   124  ```
   125  
   126  {{#/tab }}
   127  {{#tab AZURE}}
   128  
   129  An Azure Service Principal is needed for populating the controller manifests. This utilizes [environment-based authentication](https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization#use-environment-based-authentication).
   130  
   131    1. Save your Subscription ID
   132  
   133    ```bash
   134    AZURE_SUBSCRIPTION_ID=$(az account show --query id --output tsv)
   135    az account set --subscription $AZURE_SUBSCRIPTION_ID
   136    ```
   137  
   138    2. Set the Service Principal name
   139  
   140    ```bash
   141    AZURE_SERVICE_PRINCIPAL_NAME=ServicePrincipalName
   142    ```
   143  
   144    3. Save your Tenant ID, Client ID, Client Secret
   145  
   146    ```bash
   147    AZURE_TENANT_ID=$(az account show --query tenantId --output tsv)
   148    AZURE_CLIENT_SECRET=$(az ad sp create-for-rbac --name http://$AZURE_SERVICE_PRINCIPAL_NAME --query password --output tsv)
   149    AZURE_CLIENT_ID=$(az ad sp show --id http://$AZURE_SERVICE_PRINCIPAL_NAME --query appId --output tsv)
   150    ```
   151  
   152  Add the output of the following as a section in your `tilt-settings.yaml`:
   153  
   154  ```bash
   155    cat <<EOF
   156    kustomize_substitutions:
   157       AZURE_SUBSCRIPTION_ID_B64: "$(echo "${AZURE_SUBSCRIPTION_ID}" | tr -d '\n' | base64 | tr -d '\n')"
   158       AZURE_TENANT_ID_B64: "$(echo "${AZURE_TENANT_ID}" | tr -d '\n' | base64 | tr -d '\n')"
   159       AZURE_CLIENT_SECRET_B64: "$(echo "${AZURE_CLIENT_SECRET}" | tr -d '\n' | base64 | tr -d '\n')"
   160       AZURE_CLIENT_ID_B64: "$(echo "${AZURE_CLIENT_ID}" | tr -d '\n' | base64 | tr -d '\n')"
   161    EOF
   162  ```
   163  
   164  {{#/tab }}
   165  {{#tab DigitalOcean}}
   166  
   167  ```yaml
   168  kustomize_substitutions:
   169    DO_B64ENCODED_CREDENTIALS: "your credentials here"
   170  ```
   171  
   172  {{#/tab }}
   173  {{#tab GCP}}
   174  
   175  You can generate a base64 version of your GCP json credentials file using:
   176  ```bash
   177  base64 -i ~/path/to/gcp/credentials.json
   178  ```
   179  
   180  ```yaml
   181  kustomize_substitutions:
   182    GCP_B64ENCODED_CREDENTIALS: "your credentials here"
   183  ```
   184  
   185  {{#/tab }}
   186  {{#tab vSphere}}
   187  
   188  ```yaml
   189  kustomize_substitutions:
   190    VSPHERE_USERNAME: "administrator@vsphere.local"
   191    VSPHERE_PASSWORD: "Admin123"
   192  ```
   193  
   194  {{#/tab }}
   195  {{#/tabs }}
   196  
   197  **deploy_observability** ([string], default=[]): If set, installs on the dev cluster one of more observability
   198  tools.
   199  Important! This feature requires the `helm` command to be available in the user's path.
   200  
   201  Supported values are:
   202  
   203    * `grafana`*: To create dashboards and query `loki`, `prometheus` and `tempo`.
   204    * `kube-state-metrics`: For exposing metrics for Kubernetes and CAPI resources to `prometheus`.
   205    * `loki`: To receive and store logs.
   206    * `metrics-server`: To enable `kubectl top node/pod`.
   207    * `prometheus`*: For collecting metrics from Kubernetes.
   208    * `promtail`: For providing pod logs to `loki`.
   209    * `parca`*: For visualizing profiling data.
   210    * `tempo`: To store traces.
   211    * `visualizer`*: Visualize Cluster API resources for each cluster, provide quick access to the specs and status of any resource.
   212  
   213  \*: Note: the UI will be accessible via a link in the tilt console
   214  
   215  **additional_kustomizations** (map[string]string, default={}): If set, install the additional resources built using kustomize to the cluster.
   216  Example:
   217  ```yaml
   218  additional_kustomizations:
   219    capv-metrics: ../cluster-api-provider-vsphere/config/metrics
   220  ```
   221  
   222  **debug** (Map{string: Map} default{}): A map of named configurations for the provider. The key is the name of the provider.
   223  
   224  Supported settings:
   225  
   226    * **port** (int, default=0 (disabled)): If set to anything other than 0, then Tilt will run the provider with delve
   227    and port forward the delve server to localhost on the specified debug port. This can then be used with IDEs such as
   228    Visual Studio Code, Goland and IntelliJ.
   229  
   230    * **continue** (bool, default=true): By default, Tilt will run delve with `--continue`, such that any provider with
   231      debugging turned on will run normally unless specifically having a breakpoint entered. Change to false if you
   232      do not want the controller to start at all by default.
   233  
   234    * **profiler_port** (int, default=0 (disabled)): If set to anything other than 0, then Tilt will enable the profiler with
   235    `--profiler-address` and set up a port forward. A "profiler" link will be visible in the Tilt Web UI for the controller.
   236  
   237    * **metrics_port** (int, default=0 (disabled)): If set to anything other than 0, then Tilt will port forward to the
   238      default metrics port. A "metrics" link will be visible in the Tilt Web UI for the controller.
   239  
   240    * **race_detector** (bool, default=false) (Linux amd64 only): If enabled, Tilt will compile the specified controller with
   241      cgo and statically compile in the system glibc and enable the race detector. Currently, this is only supported when
   242      building on Linux amd64 systems. You must install glibc-static or have libc.a available for this to work.
   243  
   244      Example: Using the configuration below:
   245  
   246      ```yaml
   247        debug:
   248          core:
   249            continue: false
   250            port: 30000
   251            profiler_port: 40000
   252            metrics_port: 40001
   253      ```
   254  
   255      ##### Wiring up debuggers
   256      ###### Visual Studio
   257      When using the example above, the core CAPI controller can be debugged in Visual Studio Code using the following launch configuration:
   258  
   259      ```json
   260      {
   261        "version": "0.2.0",
   262        "configurations": [
   263          {
   264            "name": "Core CAPI Controller",
   265            "type": "go",
   266            "request": "attach",
   267            "mode": "remote",
   268            "remotePath": "",
   269            "port": 30000,
   270            "host": "127.0.0.1",
   271            "showLog": true,
   272            "trace": "log",
   273            "logOutput": "rpc"
   274          }
   275        ]
   276      }
   277      ```
   278  
   279      ###### Goland / IntelliJ
   280      With the above example, you can configure [a Go Remote run/debug
   281      configuration](https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html#step-3-create-the-remote-run-debug-configuration-on-the-client-computer)
   282      pointing at port 30000.
   283  
   284  <br/>
   285  
   286  **deploy_cert_manager** (Boolean, default=`true`): Deploys cert-manager into the cluster for use for webhook registration.
   287  
   288  **trigger_mode** (String, default=`auto`): Optional setting to configure if tilt should automatically rebuild on changes.
   289  Set to `manual` to disable auto-rebuilding and require users to trigger rebuilds of individual changed components through the UI.
   290  
   291  **extra_args** (Object, default={}): A mapping of provider to additional arguments to pass to the main binary configured
   292  for this provider. Each item in the array will be passed in to the manager for the given provider.
   293  
   294  Example:
   295  
   296  ```yaml
   297  extra_args:
   298    kubeadm-bootstrap:
   299    - --logging-format=json
   300  ```
   301  
   302  With this config, the respective managers will be invoked with:
   303  
   304  ```bash
   305  manager --logging-format=json
   306  ```
   307  
   308  ### Create a kind cluster and run Tilt!
   309  
   310  To create a pre-configured kind cluster (if you have not already done so) and launch your development environment, run
   311  
   312  ```bash
   313  make tilt-up
   314  ```
   315  
   316  This will open the command-line HUD as well as a web browser interface. You can monitor Tilt's status in either
   317  location. After a brief amount of time, you should have a running development environment, and you should now be able to
   318  create a cluster. There are [example worker cluster
   319  configs](https://github.com/kubernetes-sigs/cluster-api/tree/main/test/infrastructure/docker/examples) available.
   320  These can be customized for your specific needs.
   321  
   322  ### Deploying a workload cluster
   323  
   324  After your kind management cluster is up and running with Tilt, you can deploy a workload clusters in the Tilt web UI based off of YAML templates from the directories specified in
   325  the `template_dirs` field from the [tilt-settings.yaml](#tilt-settings-fields) file (default `./test/infrastructure/docker/templates`).
   326  
   327  Templates should be named according to clusterctl conventions:
   328  
   329  - template files must be named `cluster-template-{name}.yaml`; those files will be accessible in the Tilt web UI under the label grouping `{provider-label}.templates`, i.e. `CAPD.templates`.
   330  - cluster class files must be named `clusterclass-{name}.yaml`; those file will be accessible in the Tilt web UI under the label grouping `{provider-label}.clusterclasses`, i.e. `CAPD.clusterclasses`.
   331  
   332  By selecting one of those items in the Tilt web UI set of buttons will appear, allowing to create - with a dropdown for customizing variable substitutions - or delete clusters.
   333  Custom values for variable substitutions can be set using `kustomize_substitutions` in `tilt-settings.yaml`, e.g.
   334  
   335  ```yaml
   336  kustomize_substitutions:
   337    NAMESPACE: "default"
   338    KUBERNETES_VERSION: "v1.29.2"
   339    CONTROL_PLANE_MACHINE_COUNT: "1"
   340    WORKER_MACHINE_COUNT: "3"
   341  # Note: kustomize substitutions expects the values to be strings. This can be achieved by wrapping the values in quotation marks.
   342  ```
   343  
   344  ### Cleaning up your kind cluster and development environment
   345  
   346  After stopping Tilt, you can clean up your kind cluster and development environment by running
   347  
   348  ```bash
   349  make clean-kind
   350  ```
   351  
   352  To remove all generated files, run
   353  
   354  ```bash
   355  make clean
   356  ```
   357  
   358  Note that you must run `make clean` or `make clean-charts` to fetch new versions of charts deployed using `deploy_observability` in `tilt-settings.yaml`.
   359  
   360  <h1>Use of clusterctl</h1>
   361  
   362  When the worker cluster has been created using tilt, `clusterctl` should not be used for management
   363  operations; this is because tilt doesn't initialize providers on the management cluster like clusterctl init does, so
   364  some of the clusterctl commands like clusterctl config won't work.
   365  
   366  This limitation is an acceptable trade-off while executing fast dev-test iterations on controllers logic. If instead
   367  you are interested in testing clusterctl workflows, you should refer to the
   368  [clusterctl developer instructions](../clusterctl/developers.md).
   369  
   370  ## Available providers
   371  
   372  The following providers are currently defined in the Tiltfile:
   373  
   374  * **core**: cluster-api itself
   375  * **kubeadm-bootstrap**: kubeadm bootstrap provider
   376  * **kubeadm-control-plane**: kubeadm control-plane provider
   377  * **docker**: Docker infrastructure provider
   378  * **in-memory**: In-memory infrastructure provider
   379  * **test-extension**: Runtime extension used by CAPI E2E tests
   380  
   381  Additional providers can be added by following the procedure described in following paragraphs:
   382  
   383  ### tilt-provider configuration
   384  
   385  A provider must supply a `tilt-provider.yaml` file describing how to build it. Here is an example:
   386  
   387  ```yaml
   388  name: aws
   389  config:
   390    image: "gcr.io/k8s-staging-cluster-api-aws/cluster-api-aws-controller"
   391    live_reload_deps: ["main.go", "go.mod", "go.sum", "api", "cmd", "controllers", "pkg"]
   392    label: CAPA
   393  ```
   394  
   395  
   396  <aside class="note">
   397  
   398  If you prefer JSON, you can create a `tilt-provider.json` file instead. YAML will be preferred if both files are present.
   399  
   400  </aside>
   401  
   402  #### config fields
   403  
   404  **image**: the image for this provider, as referenced in the kustomize files. This must match; otherwise, Tilt won't
   405  build it.
   406  
   407  **live_reload_deps**: a list of files/directories to watch. If any of them changes, Tilt rebuilds the manager binary
   408  for the provider and performs a live update of the running container.
   409  
   410  **version**: allows to define the version to be used for the Provider CR. If empty, a default version will 
   411  be used.
   412  
   413  **additional_docker_helper_commands** (String, default=""): Additional commands to be run in the helper image
   414  docker build. e.g.
   415  
   416  ``` Dockerfile
   417  RUN wget -qO- https://dl.k8s.io/v1.21.2/kubernetes-client-linux-amd64.tar.gz | tar xvz
   418  RUN wget -qO- https://get.docker.com | sh
   419  ```
   420  
   421  **additional_docker_build_commands** (String, default=""): Additional commands to be appended to
   422  the dockerfile.
   423  The manager image will use docker-slim, so to download files, use `additional_helper_image_commands`. e.g.
   424  
   425  ``` Dockerfile
   426  COPY --from=tilt-helper /usr/bin/docker /usr/bin/docker
   427  COPY --from=tilt-helper /go/kubernetes/client/bin/kubectl /usr/bin/kubectl
   428  ```
   429  
   430  **kustomize_folder** (String, default=config/default): The folder where the kustomize file for a provider
   431  is defined; the path is relative to the provider root folder.
   432  
   433  **kustomize_options** ([]String, default=[]): Options to be applied when running kustomize for generating the
   434  yaml manifest for a provider. e.g. `"kustomize_options": [ "--load-restrictor=LoadRestrictionsNone" ]`
   435  
   436  **apply_provider_yaml** (Bool, default=true): Whether to apply the provider yaml.
   437  Set to `false` if your provider does not have a ./config folder or you do not want it to be applied in the cluster.
   438  
   439  **go_main** (String, default="main.go"): The go main file if not located at the root of the folder
   440  
   441  **label** (String, default=provider name): The label to be used to group provider components in the tilt UI
   442  in tilt version >= v0.22.2 (see https://blog.tilt.dev/2021/08/09/resource-grouping.html); as a convention,
   443  provider abbreviation should be used (CAPD, KCP etc.).
   444  
   445  **additional_resources** ([]string, default=[]): A list of paths to yaml file to be loaded into the tilt cluster;
   446  e.g. use this to deploy an ExtensionConfig object for a RuntimeExtension provider.
   447  
   448  **resource_deps** ([]string, default=[]): A list of tilt resource names to be installed before the current provider;
   449  e.g. set this to ["capi_controller"] to ensure that this provider gets installed after Cluster API.
   450  
   451  ## Customizing Tilt
   452  
   453  If you need to customize Tilt's behavior, you can create files in cluster-api's `tilt.d` directory. This file is ignored
   454  by git so you can be assured that any files you place here will never be checked in to source control.
   455  
   456  These files are included after the `providers` map has been defined and after all the helper function definitions. This
   457  is immediately before the "real work" happens.
   458  
   459  ## Under the covers, a.k.a "the real work"
   460  
   461  At a high level, the Tiltfile performs the following actions:
   462  
   463  1. Read `tilt-settings.yaml`
   464  1. Configure the allowed Kubernetes contexts
   465  1. Set the default registry
   466  1. Define the `providers` map
   467  1. Include user-defined Tilt files
   468  1. Deploy cert-manager
   469  1. Enable providers (`core` + what is listed in `tilt-settings.yaml`)
   470      1. Build the manager binary locally as a `local_resource`
   471      1. Invoke `docker_build` for the provider
   472      1. Invoke `kustomize` for the provider's `config/` directory
   473  
   474  ### Live updates
   475  
   476  Each provider in the `providers` map has a `live_reload_deps` list. This defines the files and/or directories that Tilt
   477  should monitor for changes. When a dependency is modified, Tilt rebuilds the provider's manager binary **on your local
   478  machine**, copies the binary to the running container, and executes a restart script. This is significantly faster
   479  than rebuilding the container image for each change. It also helps keep the size of each development image as small as
   480  possible (the container images do not need the entire go toolchain, source code, module dependencies, etc.).
   481  
   482  ## IDE support for Tiltfile
   483  
   484  For IntelliJ, Syntax highlighting for the Tiltfile can be configured with a TextMate Bundle. For instructions, please see:
   485  [Tiltfile TextMate Bundle](https://github.com/tilt-dev/tiltfile.tmbundle).
   486  
   487  For VSCode the [Bazel plugin](https://marketplace.visualstudio.com/items?itemName=BazelBuild.vscode-bazel) can be used, it provides
   488  syntax highlighting and auto-formatting. To enable it for Tiltfile a file association has to be configured via user settings:
   489  ```json
   490  "files.associations": {
   491    "Tiltfile": "starlark",
   492  },
   493  ```
   494  
   495  ## Using Podman
   496  
   497  [Podman](https://podman.io) can be used instead of Docker by following these actions:
   498  
   499  1. Enable the podman unix socket:
   500     - on Linux/systemd: `systemctl --user enable --now podman.socket`
   501     - on macOS: create a podman machine with `podman machine init`
   502  1. Set `build_engine` to `podman` in `tilt-settings.yaml` (optional, only if both Docker & podman are installed)
   503  1. Define the env variable `DOCKER_HOST` to the right socket:
   504     - on Linux/systemd: `export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock`
   505     - on macOS: `export DOCKER_HOST=$(podman machine inspect <machine> | jq -r '.[0].ConnectionInfo.PodmanSocket.Path')` where `<machine>` is the podman machine name
   506  1. Run `tilt up`
   507  
   508  NB: The socket defined by `DOCKER_HOST` is used only for the `hack/tools/internal/tilt-prepare` command, the image build is running the `podman build`/`podman push` commands.
   509  
   510  ## Troubleshooting Tilt
   511  
   512  ### Tilt is stuck
   513  
   514  Sometimes tilt looks stuck when it's waiting on connections.
   515  
   516  Ensure that docker/podman is up and running and your kubernetes cluster is reachable.
   517  
   518  ### Errors running tilt-prepare
   519  
   520  #### `failed to get current context from the KubeConfig file`
   521  
   522  - Ensure the cluster in the default context is reachable by running `kubectl cluster-info`
   523  - Switch to the right context with `kubectl config use-context`
   524  - Ensure the context is allowed, see [**allowed_contexts** field](#tilt-settings-fields)
   525  
   526  #### `Cannot connect to the Docker daemon`
   527  
   528  - Ensure the docker daemon is running ;) or for podman see [Using Podman](#using-podman)
   529  - If a DOCKER_HOST is specified:
   530    - check that the DOCKER_HOST has the correct prefix (usually `unix://`)
   531    - ensure docker/podman is listening on $DOCKER_HOST using `fuser` / `lsof` / `netstat -u`
   532  
   533  ### Errors pulling/pushing to the registry
   534  
   535  #### `connection refused` / `denied` / `not found`
   536  
   537  Ensure the [**default_registry** field](#tilt-settings-fields) is a valid registry where you can pull and push images.
   538  
   539  #### `server gave HTTP response to HTTPS client`
   540  
   541  By default all registries except localhost:5000 are accessed via HTTPS.
   542  
   543  If you run a HTTP registry you may have to configure the registry in docker/podman.
   544  
   545  For example, in podman a `localhost:5001` registry configuration should be declared in `/etc/containers/registries.conf.d` with this content:
   546  ````
   547  [[registry]]
   548  location = "localhost:5001"
   549  insecure = true
   550  ````
   551  
   552  NB: on macOS this configuration should be done **in the podman machine** by running `podman machine ssh <machine>`.
   553  
   554  ### Errors loading images in kind
   555  
   556  You may try manually to load images in kind by running:
   557  ````
   558  kind load docker-image --name=<kind_cluster> <image>
   559  ````
   560  
   561  #### `image: "..." not present locally`
   562  
   563  If you are running podman, you may have hit this bug: https://github.com/kubernetes-sigs/kind/issues/2760
   564  
   565  The workaround is to create a `docker` symlink to your `podman` executable and try to load the images again.