github.com/alloyci/alloy-runner@v1.0.1-0.20180222164613-925503ccafd6/docs/executors/kubernetes.md (about)

     1  # The Kubernetes executor
     2  
     3  AlloyCI Runner can use Kubernetes to run builds on a kubernetes cluster. This is
     4  possible with the use of the **Kubernetes** executor.
     5  
     6  The **Kubernetes** executor, when used with AlloyCI CI, connects to the Kubernetes
     7  API in the cluster creating a Pod for each AlloyCI CI Job. This Pod is made
     8  up of, at the very least, a build container and an additional container for each
     9  `service` defined by the AlloyCI CI yaml. The names for these containers
    10  are as follows:
    11  
    12  - The build container is `build`
    13  - The services containers are `svc-X` where `X` is `[0-9]+`
    14  
    15  Note that when services and containers are running in the same Kubernetes
    16  pod, they are all sharing the same localhost address. The following restrictions
    17  are then applicable:
    18  
    19  - The services are *not* accessible via their DNS name, you need to use localhost
    20    instead.
    21  - You cannot use several services using the same port (e.g., you cannot have two
    22    `mysql` services at the same time).
    23  
    24  ## Workflow
    25  
    26  The Kubernetes executor divides the build into multiple steps:
    27  
    28  1. **Prepare**: Create the Pod against the Kubernetes Cluster.
    29  	This creates the containers required for the build and services to run.
    30  1. **Pre-build**: Clone, restore cache and download artifacts from previous
    31     stages. This is run on a special container as part of the Pod.
    32  1. **Build**: User build.
    33  1. **Post-build**: Create cache, upload artifacts to AlloyCI. This also uses
    34     the special container as part of the Pod.
    35  
    36  ## Connecting to the Kubernetes API
    37  
    38  The following options are provided, which allow you to connect to the Kubernetes API:
    39  
    40  - `host`: Optional Kubernetes apiserver host URL (auto-discovery attempted if not specified)
    41  - `cert_file`: Optional Kubernetes apiserver user auth certificate
    42  - `key_file`: Optional Kubernetes apiserver user auth private key
    43  - `ca_file`: Optional Kubernetes apiserver ca certificate
    44  
    45  The user account provided must have permission to create, list and attach to Pods in
    46  the specified namespace in order to function.
    47  
    48  If you are running the AlloyCI Runner within the Kubernetes cluster you can omit
    49  all of the above fields to have the Runner auto-discovery the Kubernetes API. This
    50  is the recommended approach.
    51  
    52  If you are running it externally to the Cluster then you will need to set each
    53  of these keywords and make sure that the Runner has access to the Kubernetes API
    54  on the cluster.
    55  
    56  ## The keywords
    57  
    58  The following keywords help to define the behaviour of the Runner within Kubernetes:
    59  
    60  - `namespace`: Namespace to run Kubernetes Pods in
    61  - `namespace_overwrite_allowed`: Regular expression to validate the contents of
    62    the namespace overwrite environment variable (documented following). When empty,
    63    it disables the namespace overwrite feature
    64  - `privileged`: Run containers with the privileged flag
    65  - `cpu_limit`: The CPU allocation given to build containers
    66  - `memory_limit`: The amount of memory allocated to build containers
    67  - `service_cpu_limit`: The CPU allocation given to build service containers
    68  - `service_memory_limit`: The amount of memory allocated to build service containers
    69  - `helper_cpu_limit`: The CPU allocation given to build helper containers
    70  - `helper_memory_limit`: The amount of memory allocated to build helper containers
    71  - `cpu_request`: The CPU allocation requested for build containers
    72  - `memory_request`: The amount of memory requested from build containers
    73  - `service_cpu_request`: The CPU allocation requested for build service containers
    74  - `service_memory_request`: The amount of memory requested for build service containers
    75  - `helper_cpu_request`: The CPU allocation requested for build helper containers
    76  - `helper_memory_request`: The amount of memory requested for build helper containers
    77  - `pull_policy`: specify the image pull policy: `never`, `if-not-present`, `always`. The cluster default will be used if not set.
    78  - `node_selector`: A `table` of `key=value` pairs of `string=string`. Setting this limits the creation of pods to kubernetes nodes matching all the `key=value` pairs
    79  - `image_pull_secrets`: A array of secrets that are used to authenticate docker image pulling
    80  - `helper_image`: [ADVANCED] Override the default helper image used to clone repos and upload artifacts
    81  - `terminationGracePeriodSeconds`: Duration after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal
    82  - `poll_interval`: How frequently, in seconds, the runner will poll the Kubernetes pod it has just created to check its status. [Default: 3]
    83  - `poll_timeout`: The amount of time, in seconds, that needs to pass before the runner will timeout attempting to connect to the container it has just created (useful for queueing more builds that the cluster can handle at a time) [Default: 180]
    84  - `pod_labels`: A set of labels to be added to each build pod created by the runner. The value of these can include environment variables for expansion.
    85  - `pod_annotations`: A set of annotations to be added to each build pod created by the Runner. The value of these can include environment variables for expansion. Pod annotations can be overwritten in each build.
    86  - `pod_annotations_overwrite_allowed`: Regular expression to validate the contents of
    87    the pod annotations overwrite environment variable. When empty,
    88      it disables the pod annotations overwrite feature
    89  - `service-account`: default service account to be used for making kubernetes api calls.
    90  - `service_account_overwrite_allowed`: Regular expression to validate the contents of
    91    the service account overwrite environment variable. When empty,
    92      it disables the service account overwrite feature
    93  - `bearer-token`: Default bearer token used to launch build pods.
    94  - `bearer_token_overwrite_allowed`: Boolean to allow projects to specify a bearer token that will be used to create the build pod.
    95  - `volumes`: configured through the config file, the list of volumes that will be mounted in the build container. [Read more about using volumes.](#using-volumes)
    96  
    97  ### Configuring executor Service Account
    98  
    99  You can set the `KUBERNETES_SERVICE_ACCOUNT` environment variable or use `--service-account` flag
   100  
   101  ### Overwriting Kubernetes Namespace
   102  
   103  Additionally, Kubernetes namespace can be overwritten on `.alloy-ci.json` file, by using the variable
   104  `KUBERNETES_NAMESPACE_OVERWRITE`.
   105  
   106  This approach allow you to create a new isolated namespace dedicated for CI purposes, and deploy a custom
   107  set of Pods. The `Pods` spawned by the runner will take place on the overwritten namespace, for simple
   108  and straight forward access between container during the CI stages.
   109  
   110  ``` yaml
   111  variables:
   112    KUBERNETES_NAMESPACE_OVERWRITE: ci-${CI_COMMIT_REF_NAME}
   113  ```
   114  
   115  Furthermore, to ensure only designated namespaces will be used during CI runs, inform the configuration
   116  `namespace_overwrite_allowed` with proper regular expression. When left empty the overwrite behaviour is
   117  disabled.
   118  
   119  ### Overwriting Kubernetes Default Service Account
   120  
   121  Additionally, Kubernetes service account can be overwritten on `.alloy-ci.json` file, by using the variable
   122  `KUBERNETES_SERVICE_ACCOUNT_OVERWRITE`.
   123  
   124  This approach allow you to specify a service account that is attached to the namespace, usefull when dealing
   125  with complex RBAC configurations.
   126  ``` yaml
   127  variables:
   128    KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: ci-service-account
   129  ```
   130  usefull when overwritting the namespace and RBAC is setup in the cluster.
   131  
   132  To ensure only designated service accounts will be used during CI runs, inform the configuration
   133   `service_account_overwrite_allowed` or set the environment variable `KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED`
   134   with proper regular expression. When left empty the overwrite behaviour is disabled.
   135  
   136  ### Setting Bearer Token to be Used When Making Kubernetes API calls
   137  
   138  In conjunction with setting the namespace and service account as mentioned above, you may set the bearer token used when making API calls to create the build pods.  This will allow project owners to use project secret variables to specify a bearer token.  When specifying the bearer token, it is required that you set the `Host` config keyword.
   139  ``` yaml
   140  variables:
   141    KUBERNETES_BEARER_TOKEN: thebearertokenfromanothernamespace
   142  ```
   143  
   144  ### Overwriting pod annotations
   145  
   146  Additionally, Kubernetes pod annotations can be overwritten on the `.alloy-ci.json` file, by using `KUBERNETES_POD_ANNOTATIONS_*` for variables and `key=value` for the value. The pod annotations will be overwritten to the `key=value`. Also, multiple annotations can be applied. For example:
   147  ``` yaml
   148   variables:
   149     KUBERNETES_POD_ANNOTATIONS_1: "Key1=Val1"
   150     KUBERNETES_POD_ANNOTATIONS_2: "Key2=Val2"
   151     KUBERNETES_POD_ANNOTATIONS_3: "Key3=Val3"
   152  ```
   153  
   154  ## Define keywords in the config toml
   155  
   156  Each of the keywords can be defined in the `config.toml` for the alloy runner.
   157  
   158  Here is an example `config.toml`:
   159  
   160  ```toml
   161  concurrent = 4
   162  
   163  [[runners]]
   164    name = "Kubernetes Runner"
   165    url = "https://alloy.com/ci"
   166    token = "......"
   167    executor = "kubernetes"
   168    [runners.kubernetes]
   169      host = "https://45.67.34.123:4892"
   170      cert_file = "/etc/ssl/kubernetes/api.crt"
   171      key_file = "/etc/ssl/kubernetes/api.key"
   172      ca_file = "/etc/ssl/kubernetes/ca.crt"
   173      namespace = "alloy"
   174      namespace_overwrite_allowed = "ci-.*"
   175      bearer_token_overwrite_allowed = true
   176      privileged = true
   177      cpu_limit = "1"
   178      memory_limit = "1Gi"
   179      service_cpu_limit = "1"
   180      service_memory_limit = "1Gi"
   181      helper_cpu_limit = "500m"
   182      helper_memory_limit = "100Mi"
   183      poll_interval = 5
   184      poll_timeout = 3600
   185      [runners.kubernetes.node_selector]
   186        alloy = "true"
   187  ```
   188  
   189  ## Using volumes
   190  
   191  As described earlier, volumes can be mounted in the build container.
   192  At this time _hostPath_, _PVC_, _configMap_, and _secret_ volume types
   193  are supported. User can configure any number of volumes for each of
   194  mentioned types.
   195  
   196  Here is an example configuration:
   197  
   198  ```toml
   199  concurrent = 4
   200  
   201  [[runners]]
   202    # usual configuration
   203    executor = "kubernetes"
   204    [runners.kubernetes]
   205      [[runners.kubernetes.volumes.host_path]]
   206        name = "hostpath-1"
   207        mount_path = "/path/to/mount/point"
   208        read_only = true
   209        host_path = "/path/on/host"
   210      [[runners.kubernetes.volumes.host_path]]
   211        name = "hostpath-2"
   212        mount_path = "/path/to/mount/point_2"
   213        read_only = true
   214      [[runners.kubernetes.volumes.pvc]]
   215        name = "pvc-1"
   216        mount_path = "/path/to/mount/point1"
   217      [[runners.kubernetes.volumes.config_map]]
   218        name = "config-map-1"
   219        mount_path = "/path/to/directory"
   220        [runners.kubernetes.volumes.config_map.items]
   221          "key_1" = "relative/path/to/key_1_file"
   222          "key_2" = "key_2"
   223      [[runners.kubernetes.volumes.secret]]
   224        name = "secrets"
   225        mount_path = "/path/to/directory1"
   226        read_only = true
   227        [runners.kubernetes.volumes.secret.items]
   228          "secret_1" = "relative/path/to/secret_1_file"
   229      [[runners.kubernetes.volumes.empty_dir]]
   230        name = "empty_dir"
   231        mount_path = "/path/to/empty_dir"
   232        medium = "Memory"
   233  ```
   234  
   235  ### Host Path volumes
   236  
   237  [_HostPath_ volume][k8s-host-path-volume-docs] configuration instructs Kubernetes to mount
   238  a specified host path inside of the container. The volume can be configured with
   239  following options:
   240  
   241  | Option     | Type    | Required | Description |
   242  |------------|---------|----------|-------------|
   243  | name       | string  | yes      | The name of the volume |
   244  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   245  | host_path  | string  | no       | Host's path that should be mounted as volume. If not specified then set to the same path as `mount_path`. |
   246  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   247  
   248  ### PVC volumes
   249  
   250  [_PVC_ volume][k8s-pvc-volume-docs] configuration instructs Kubernetes to use a _PersistentVolumeClaim_
   251  that is defined in Kubernetes cluster and mount it inside of the container. The volume
   252  can be configured with following options:
   253  
   254  | Option     | Type    | Required | Description |
   255  |------------|---------|----------|-------------|
   256  | name       | string  | yes      | The name of the volume and at the same time the name of _PersistentVolumeClaim_ that should be used |
   257  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   258  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   259  
   260  ### Config Map volumes
   261  
   262  _ConfigMap_ volume configuration instructs Kubernetes to use a [_configMap_][k8s-config-map-docs]
   263  that is defined in Kubernetes cluster and mount it inside of the container.
   264  
   265  | Option     | Type    | Required | Description |
   266  |------------|---------|----------|-------------|
   267  | name       | string  | yes      | The name of the volume and at the same time the name of _configMap_ that should be used |
   268  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   269  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   270  | items      | map[string]string | no | Key-to-path mapping for keys from the _configMap_ that should be used. |
   271  
   272  When using _configMap_ volume, each key from selected _configMap_ will be changed into a file
   273  stored inside of the selected mount path. By default all keys are present, _configMap's_ key
   274  is used as file's name and value is stored as file's content. The default behavior can be
   275  changed with `items` option.
   276  
   277  `items` option is defining a mapping between key that should be used and path (relative
   278  to volume's mount path) where _configMap's_ value should be saved. When using `items` option
   279  **only selected keys** will be added to the volumes and all other will be skipped.
   280  
   281  > **Notice**: If a non-existing key will be used then job will fail on Pod creation stage.
   282  
   283  ### Secret volumes
   284  
   285  [_Secret_ volume][k8s-secret-volume-docs] configuration instructs Kubernetes to use
   286  a _secret_ that is defined in Kubernetes cluster and mount it inside of the container.
   287  
   288  | Option     | Type    | Required | Description |
   289  |------------|---------|----------|-------------|
   290  | name       | string  | yes      | The name of the volume and at the same time the name of _secret_ that should be used |
   291  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   292  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   293  | items      | map[string]string | no | Key-to-path mapping for keys from the _secret_ that should be used. |
   294  
   295  When using _secret_ volume each key from selected _secret_ will be changed into a file
   296  stored inside of the selected mount path. By default all keys are present, _secret's_ key
   297  is used as file's name and value is stored as file's content. The default behavior can be
   298  changed with `items` option.
   299  
   300  `items` option is defining a mapping between key that should be used and path (relative
   301  to volume's mount path) where _secret's_ value should be saved. When using `items` option
   302  **only selected keys** will be added to the volumes and all other will be skipped.
   303  
   304  > **Notice**: If a non-existing key will be used then job will fail on Pod creation stage.
   305  
   306  ### Empty Dir volumes
   307  
   308  [_emptyDir_ volume][k8s-empty-dir-volume-docs] configuration instructs Kubernetes to mount an empty directory inside of the container.
   309  
   310  | Option     | Type    | Required | Description |
   311  |------------|---------|----------|-------------|
   312  | name       | string  | yes      | The name of the volume |
   313  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   314  | medium     | String  | no       | "Memory" will provide a tmpfs, otherwise it defaults to the node disk storage (defaults to "") |
   315  
   316  ## Using Docker in your builds
   317  
   318  There are a couple of caveats when using docker in your builds while running on
   319  a kubernetes cluster. Most of these issues are already discussed in the
   320  [**Using Docker Build**](https://docs.gitlab.com/ce/ci/docker/using_docker_build.html)
   321  section of the gitlab-ci
   322  documentation but it is worth it to revisit them here as you might run into
   323  some slightly different things when running this on your cluster.
   324  
   325  ### Exposing `/var/run/docker.sock`
   326  Exposing your host's `/var/run/docker.sock` into your build container, using the
   327  `runners.kubernetes.volumes.host_path` option, brings the same risks with it as
   328  always. That node's containers are accessible from the build container and
   329  depending if you are running builds in the same cluster as your production
   330  containers it might not be wise to do that.
   331  
   332  ### Using `docker:dind`
   333  Running the `docker:dind` also known as the `docker-in-docker` image is also
   334  possible but sadly needs the containers to be run in privileged mode.
   335  If you're willing to take that risk other problems will arise that might not
   336  seem as straight forward at first glance. Because the docker daemon is started
   337  as a `service` usually in your `.alloy-ci.json` it will be run as a separate
   338  container in your Pod. Basically containers in Pods only share volumes assigned
   339  to them and an IP address by which they can reach each other using `localhost`.
   340  `/var/run/docker.sock` is not shared by the `docker:dind` container and the `docker`
   341  binary tries to use it by default. To overwrite this and make the client use tcp
   342  to contact the docker daemon in the other container be sure to include
   343  `DOCKER_HOST=tcp://localhost:2375` in your environment variables of the build container.
   344  
   345  ### Not supplying git
   346  Do *not* try to use an image that doesn't supply git and add the `GIT_STRATEGY=none`
   347  environment variable for a job that you think doesn't need to do a fetch or clone.
   348  Because Pods are ephemeral and do not keep state of previously run jobs your
   349  checked out code will not exist in both the build and the docker service container.
   350  Error's you might run into are things like `could not find git binary` and
   351  the docker service complaining that it cannot follow some symlinks into your
   352  build context because of the missing code.
   353  
   354  ### Resource separation
   355  In both the `docker:dind` and `/var/run/docker.sock` cases the docker daemon
   356  has access to the underlying kernel of the host machine. This means that any
   357  `limits` that had been set in the Pod will not work when building docker images.
   358  The docker daemon will report the full capacity of the node regardless of
   359  the limits imposed on the docker build containers spawned by kubernetes.
   360    
   361  ```
   362  # usual configuration
   363  
   364  executor = "kubernetes"
   365  [runners.kubernetes]
   366    [[runners.kubernetes.volumes.host_path]]
   367      name = "hostpath-1"
   368      mount_path = "/path/to/mount/point"
   369      read_only = true
   370      host_path = "/path/on/host"
   371    [[runners.kubernetes.volumes.host_path]]
   372      name = "hostpath-2"
   373      mount_path = "/path/to/mount/point_2"
   374      read_only = true
   375    [[runners.kubernetes.volumes.pvc]]
   376      name = "pvc-1"
   377      mount_path = "/path/to/mount/point1"
   378    [[runners.kubernetes.volumes.config_map]]
   379      name = "config-map-1"
   380      mount_path = "/path/to/directory"
   381      [runners.kubernetes.volumes.config_map.items]
   382        "key_1" = "relative/path/to/key_1_file"
   383        "key_2" = "key_2"
   384    [[runners.kubernetes.volumes.secret]]
   385      name = "secrets"
   386      mount_path = "/path/to/directory1"
   387      read_only = true
   388      [runners.kubernetes.volumes.secret.items]
   389        "secret_1" = "relative/path/to/secret_1_file"
   390    [[runners.kubernetes.volumes.empty_dir]]
   391      name = "empty_dir"
   392      mount_path = "/path/to/empty_dir"
   393      medium = "Memory"
   394  ```
   395  
   396  ### Host Path volumes
   397  
   398  [_HostPath_ volume][k8s-host-path-volume-docs] configuration instructs Kubernetes to mount
   399  a specified host path inside of the container. The volume can be configured with
   400  following options:
   401  
   402  | Option     | Type    | Required | Description |
   403  |------------|---------|----------|-------------|
   404  | name       | string  | yes      | The name of the volume |
   405  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   406  | host_path  | string  | no       | Host's path that should be mounted as volume. If not specified then set to the same path as `mount_path`. |
   407  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   408  
   409  ### PVC volumes
   410  
   411  [_PVC_ volume][k8s-pvc-volume-docs] configuration instructs Kubernetes to use a _PersistentVolumeClaim_
   412  that is defined in Kubernetes cluster and mount it inside of the container. The volume
   413  can be configured with following options:
   414  
   415  | Option     | Type    | Required | Description |
   416  |------------|---------|----------|-------------|
   417  | name       | string  | yes      | The name of the volume and at the same time the name of _PersistentVolumeClaim_ that should be used |
   418  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   419  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   420  
   421  ### Config Map volumes
   422  
   423  _ConfigMap_ volume configuration instructs Kubernetes to use a [_configMap_][k8s-config-map-docs]
   424  that is defined in Kubernetes cluster and mount it inside of the container.
   425  
   426  | Option     | Type    | Required | Description |
   427  |------------|---------|----------|-------------|
   428  | name       | string  | yes      | The name of the volume and at the same time the name of _configMap_ that should be used |
   429  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   430  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   431  | items      | map[string]string | no | Key-to-path mapping for keys from the _configMap_ that should be used. |
   432  
   433  When using _configMap_ volume, each key from selected _configMap_ will be changed into a file
   434  stored inside of the selected mount path. By default all keys are present, _configMap's_ key
   435  is used as file's name and value is stored as file's content. The default behavior can be
   436  changed with `items` option.
   437  
   438  `items` option is defining a mapping between key that should be used and path (relative
   439  to volume's mount path) where _configMap's_ value should be saved. When using `items` option
   440  **only selected keys** will be added to the volumes and all other will be skipped.
   441  
   442  > **Notice**: If a non-existing key will be used then job will fail on Pod creation stage.
   443  
   444  ### Secret volumes
   445  
   446  [_Secret_ volume][k8s-secret-volume-docs] configuration instructs Kubernetes to use
   447  a _secret_ that is defined in Kubernetes cluster and mount it inside of the container.
   448  
   449  | Option     | Type    | Required | Description |
   450  |------------|---------|----------|-------------|
   451  | name       | string  | yes      | The name of the volume and at the same time the name of _secret_ that should be used |
   452  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   453  | read_only  | boolean | no       | Set's the volume in read-only mode (defaults to false) |
   454  | items      | map[string]string | no | Key-to-path mapping for keys from the _secret_ that should be used. |
   455  
   456  When using _secret_ volume each key from selected _secret_ will be changed into a file
   457  stored inside of the selected mount path. By default all keys are present, _secret's_ key
   458  is used as file's name and value is stored as file's content. The default behavior can be
   459  changed with `items` option.
   460  
   461  `items` option is defining a mapping between key that should be used and path (relative
   462  to volume's mount path) where _secret's_ value should be saved. When using `items` option
   463  **only selected keys** will be added to the volumes and all other will be skipped.
   464  
   465  > **Notice**: If a non-existing key will be used then job will fail on Pod creation stage.
   466  
   467  ### Empty Dir volumes
   468  
   469  [_emptyDir_ volume][k8s-empty-dir-volume-docs] configuration instructs Kubernetes to mount an empty directory inside of the container.
   470  
   471  | Option     | Type    | Required | Description |
   472  |------------|---------|----------|-------------|
   473  | name       | string  | yes      | The name of the volume |
   474  | mount_path | string  | yes      | Path inside of container where the volume should be mounted |
   475  | medium     | String  | no       | "Memory" will provide a tmpfs, otherwise it defaults to the node disk storage (defaults to "") |
   476  
   477  ## Using Docker in your builds
   478  
   479  There are a couple of caveats when using docker in your builds while running on
   480  a kubernetes cluster. Most of these issues are already discussed in the
   481  [**Using Docker Build**](https://docs.alloy.com/ce/ci/docker/using_docker_build.html)
   482  section of the alloy-ci
   483  documentation but it is worth it to revisit them here as you might run into
   484  some slightly different things when running this on your cluster.
   485  
   486  ### Exposing `/var/run/docker.sock`
   487  Exposing your host's `/var/run/docker.sock` into your build container, using the
   488  `runners.kubernetes.volumes.host_path` option, brings the same risks with it as
   489  always. That node's containers are accessible from the build container and
   490  depending if you are running builds in the same cluster as your production
   491  containers it might not be wise to do that.
   492  
   493  ### Using `docker:dind`
   494  Running the `docker:dind` also known as the `docker-in-docker` image is also
   495  possible but sadly needs the containers to be run in privileged mode.
   496  If you're willing to take that risk other problems will arise that might not
   497  seem as straight forward at first glance. Because the docker daemon is started
   498  as a `service` usually in your `.alloy-ci.json` it will be run as a separate
   499  container in your Pod. Basically containers in Pods only share volumes assigned
   500  to them and an IP address by which they can reach each other using `localhost`.
   501  `/var/run/docker.sock` is not shared by the `docker:dind` container and the `docker`
   502  binary tries to use it by default. To overwrite this and make the client use tcp
   503  to contact the docker daemon in the other container be sure to include
   504  `DOCKER_HOST=tcp://localhost:2375` in your environment variables of the build container.
   505  
   506  ### Not supplying git
   507  Do *not* try to use an image that doesn't supply git and add the `GIT_STRATEGY=none`
   508  environment variable for a job that you think doesn't need to do a fetch or clone.
   509  Because Pods are ephemeral and do not keep state of previously run jobs your
   510  checked out code will not exist in both the build and the docker service container.
   511  Error's you might run into are things like `could not find git binary` and
   512  the docker service complaining that it cannot follow some symlinks into your
   513  build context because of the missing code.
   514  
   515  ### Resource separation
   516  In both the `docker:dind` and `/var/run/docker.sock` cases the docker daemon
   517  has access to the underlying kernel of the host machine. This means that any
   518  `limits` that had been set in the Pod will not work when building docker images.
   519  The docker daemon will report the full capacity of the node regardless of
   520  the limits imposed on the docker build containers spawned by kubernetes.
   521  
   522  One way to help minimize the exposure of the host's kernel to any build container
   523  when running in privileged mode or by exposing `/var/run/docker.sock` is to use
   524  the `node_selector` option to set one or more labels that have to match a node
   525  before any containers are deployed to it. For example build containers may only run
   526  on nodes that are labeled with `role=ci` while running all other production services
   527  on other nodes.
   528  
   529  [k8s-host-path-volume-docs]: https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
   530  [k8s-pvc-volume-docs]: https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim
   531  [k8s-secret-volume-docs]: https://kubernetes.io/docs/concepts/storage/volumes/#secret
   532  [k8s-config-map-docs]: https://kubernetes.io/docs/tasks/configure-pod-container/configmap/
   533  [k8s-empty-dir-volume-docs]:https://kubernetes.io/docs/concepts/storage/volumes/#emptydir