Move Guide topics: Container Lifestyle Hooks, Images, Volumes
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
---
|
||||
assignees:
|
||||
- mikedanese
|
||||
- thockin
|
||||
title: Container Lifecycle Hooks
|
||||
---
|
||||
|
||||
This document describes the environment for Kubelet managed containers on a Kubernetes node (kNode). In contrast to the Kubernetes cluster API, which provides an API for creating and managing containers, the Kubernetes container environment provides the container access to information about what else is going on in the cluster.
|
||||
|
||||
This cluster information makes it possible to build applications that are *cluster aware*.
|
||||
Additionally, the Kubernetes container environment defines a series of hooks that are surfaced to optional hook handlers defined as part of individual containers. Container hooks are somewhat analogous to operating system signals in a traditional process model. However these hooks are designed to make it easier to build reliable, scalable cloud applications in the Kubernetes cluster. Containers that participate in this cluster lifecycle become *cluster native*.
|
||||
|
||||
Another important part of the container environment is the file system that is available to the container. In Kubernetes, the filesystem is a combination of an [image](/docs/concepts/containers/images/) and one or more [volumes](/docs/concepts/storage/volumes/).
|
||||
|
||||
The following sections describe both the cluster information provided to containers, as well as the hooks and life-cycle that allows containers to interact with the management system.
|
||||
|
||||
* TOC
|
||||
{:toc}
|
||||
|
||||
## Cluster Information
|
||||
|
||||
There are two types of information that are available within the container environment. There is information about the container itself, and there is information about other objects in the system.
|
||||
|
||||
### Container Information
|
||||
|
||||
Currently, the Pod name for the pod in which the container is running is set as the hostname of the container, and is accessible through all calls to access the hostname within the container (e.g. the hostname command, or the [gethostname][1] function call in libc), but this is planned to change in the future and should not be used.
|
||||
|
||||
The Pod name and namespace are also available as environment variables via the [downward API](/docs/user-guide/downward-api). Additionally, user-defined environment variables from the pod definition, are also available to the container, as are any environment variables specified statically in the Docker image.
|
||||
|
||||
In the future, we anticipate expanding this information with richer information about the container. Examples include available memory, number of restarts, and in general any state that you could get from the call to GET /pods on the API server.
|
||||
|
||||
### Cluster Information
|
||||
|
||||
Currently the list of all services that are running at the time when the container was created via the Kubernetes Cluster API are available to the container as environment variables. The set of environment variables matches the syntax of Docker links.
|
||||
|
||||
For a service named **foo** that maps to a container port named **bar**, the following variables are defined:
|
||||
|
||||
```shell
|
||||
FOO_SERVICE_HOST=<the host the service is running on>
|
||||
FOO_SERVICE_PORT=<the port the service is running on>
|
||||
```
|
||||
|
||||
Services have dedicated IP address, and are also surfaced to the container via DNS (If [DNS addon](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/) is enabled). Of course DNS is still not an enumerable protocol, so we will continue to provide environment variables so that containers can do discovery.
|
||||
|
||||
## Container Hooks
|
||||
|
||||
Container hooks provide information to the container about events in its management lifecycle. For example, immediately after a container is started, it receives a *PostStart* hook. These hooks are broadcast *into* the container with information about the life-cycle of the container. They are different from the events provided by Docker and other systems which are *output* from the container. Output events provide a log of what has already happened. Input hooks provide real-time notification about things that are happening, but no historical log.
|
||||
|
||||
### Hook Details
|
||||
|
||||
There are currently two container hooks that are surfaced to containers:
|
||||
|
||||
*PostStart*
|
||||
|
||||
This hook is sent immediately after a container is created. It notifies the container that it has been created. No parameters are passed to the handler. It is NOT guaranteed that the hook will execute before the container entrypoint.
|
||||
|
||||
*PreStop*
|
||||
|
||||
This hook is called immediately before a container is terminated. No parameters are passed to the handler. This event handler is blocking, and must complete before the call to delete the container is sent to the Docker daemon. The SIGTERM notification sent by Docker is also still sent. A more complete description of termination behavior can be found in [Termination of Pods](/docs/user-guide/pods/#termination-of-pods).
|
||||
|
||||
### Hook Handler Execution
|
||||
|
||||
When a management hook occurs, the management system calls into any registered hook handlers in the container for that hook. These hook handler calls are synchronous in the context of the pod containing the container. This means that for a `PostStart` hook, the container entrypoint and hook will fire asynchronously. However, if the hook takes a while to run or hangs, the container will never reach a "running" state. The behavior is similar for a `PreStop` hook. If the hook hangs during execution, the Pod phase will stay in a "running" state and never reach "failed." If a `PostStart` or `PreStop` hook fails, it will kill the container.
|
||||
|
||||
Typically we expect that users will make their hook handlers as lightweight as possible, but there are cases where long running commands make sense (e.g. saving state prior to container stop).
|
||||
|
||||
### Hook delivery guarantees
|
||||
|
||||
Hook delivery is intended to be "at least once", which means that a hook may be called multiple times for any given event (e.g. "start" or "stop") and it is up to the hook implementer to be able to handle this
|
||||
correctly.
|
||||
|
||||
We expect double delivery to be rare, but in some cases if the Kubelet restarts in the middle of sending a hook, the hook may be resent after the Kubelet comes back up.
|
||||
|
||||
Likewise, we only make a single delivery attempt. If (for example) an http hook receiver is down, and unable to take traffic, we do not make any attempts to resend.
|
||||
|
||||
Currently, there are (hopefully rare) scenarios where PostStart hooks may not be delivered.
|
||||
|
||||
### Hook Handler Implementations
|
||||
|
||||
Hook handlers are the way that hooks are surfaced to containers. Containers can select the type of hook handler they would like to implement. Kubernetes currently supports two different hook handler types:
|
||||
|
||||
* Exec - Executes a specific command (e.g. pre-stop.sh) inside the cgroups and namespaces of the container. Resources consumed by the command are counted against the container.
|
||||
|
||||
* HTTP - Executes an HTTP request against a specific endpoint on the container.
|
||||
|
||||
[1]: http://man7.org/linux/man-pages/man2/gethostname.2.html
|
||||
|
||||
### Debugging Hook Handlers
|
||||
|
||||
Currently, the logs for a hook handler are not exposed in the pod events. If your handler fails for some reason, it will emit an event. For `PostStart`, this is the `FailedPostStartHook` event. For `PreStop` this is the `FailedPreStopHook` event. You can see these events by running `kubectl describe pod <pod_name>`. An example output of events from runing this command is below:
|
||||
|
||||
```
|
||||
Events:
|
||||
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
|
||||
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
|
||||
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
|
||||
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
|
||||
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
|
||||
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
|
||||
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
|
||||
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
|
||||
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
|
||||
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
|
||||
```
|
||||
@@ -0,0 +1,320 @@
|
||||
---
|
||||
assignees:
|
||||
- erictune
|
||||
- thockin
|
||||
title: Images
|
||||
---
|
||||
|
||||
Each container in a pod has its own image. Currently, the only type of image supported is a [Docker Image](https://docs.docker.com/engine/tutorials/dockerimages/).
|
||||
|
||||
You create your Docker image and push it to a registry before referring to it in a Kubernetes pod.
|
||||
|
||||
The `image` property of a container supports the same syntax as the `docker` command does, including private registries and tags.
|
||||
|
||||
* TOC
|
||||
{:toc}
|
||||
|
||||
|
||||
## Updating Images
|
||||
|
||||
The default pull policy is `IfNotPresent` which causes the Kubelet to not
|
||||
pull an image if it already exists. If you would like to always force a pull
|
||||
you must set a pull image policy of `Always` or specify a `:latest` tag on
|
||||
your image.
|
||||
|
||||
If you did not specify tag of your image, it will be assumed as `:latest`, with
|
||||
pull image policy of `Always` correspondingly.
|
||||
|
||||
Note that you should avoid using `:latest` tag, see [Best Practices for Configuration](/docs/concepts/configuration/overview/#container-images) for more information.
|
||||
|
||||
## Using a Private Registry
|
||||
|
||||
Private registries may require keys to read images from them.
|
||||
Credentials can be provided in several ways:
|
||||
|
||||
- Using Google Container Registry
|
||||
- Per-cluster
|
||||
- automatically configured on Google Compute Engine or Google Container Engine
|
||||
- all pods can read the project's private registry
|
||||
- Using AWS EC2 Container Registry (ECR)
|
||||
- use IAM roles and policies to control access to ECR repositories
|
||||
- automatically refreshes ECR login credentials
|
||||
- Using Azure Container Registry (ACR)
|
||||
- Configuring Nodes to Authenticate to a Private Registry
|
||||
- all pods can read any configured private registries
|
||||
- requires node configuration by cluster administrator
|
||||
- Pre-pulling Images
|
||||
- all pods can use any images cached on a node
|
||||
- requires root access to all nodes to setup
|
||||
- Specifying ImagePullSecrets on a Pod
|
||||
- only pods which provide own keys can access the private registry
|
||||
Each option is described in more detail below.
|
||||
|
||||
|
||||
### Using Google Container Registry
|
||||
|
||||
Kubernetes has native support for the [Google Container
|
||||
Registry (GCR)](https://cloud.google.com/tools/container-registry/), when running on Google Compute
|
||||
Engine (GCE). If you are running your cluster on GCE or Google Container Engine (GKE), simply
|
||||
use the full image name (e.g. gcr.io/my_project/image:tag).
|
||||
|
||||
All pods in a cluster will have read access to images in this registry.
|
||||
|
||||
The kubelet will authenticate to GCR using the instance's
|
||||
Google service account. The service account on the instance
|
||||
will have a `https://www.googleapis.com/auth/devstorage.read_only`,
|
||||
so it can pull from the project's GCR, but not push.
|
||||
|
||||
### Using AWS EC2 Container Registry
|
||||
|
||||
Kubernetes has native support for the [AWS EC2 Container
|
||||
Registry](https://aws.amazon.com/ecr/), when nodes are AWS EC2 instances.
|
||||
|
||||
Simply use the full image name (e.g. `ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag`)
|
||||
in the Pod definition.
|
||||
|
||||
All users of the cluster who can create pods will be able to run pods that use any of the
|
||||
images in the ECR registry.
|
||||
|
||||
The kubelet will fetch and periodically refresh ECR credentials. It needs the following permissions to do this:
|
||||
|
||||
- `ecr:GetAuthorizationToken`
|
||||
- `ecr:BatchCheckLayerAvailability`
|
||||
- `ecr:GetDownloadUrlForLayer`
|
||||
- `ecr:GetRepositoryPolicy`
|
||||
- `ecr:DescribeRepositories`
|
||||
- `ecr:ListImages`
|
||||
- `ecr:BatchGetImage`
|
||||
|
||||
Requirements:
|
||||
|
||||
- You must be using kubelet version `v1.2.0` or newer. (e.g. run `/usr/bin/kubelet --version=true`).
|
||||
- If your nodes are in region A and your registry is in a different region B, you need version `v1.3.0` or newer.
|
||||
- ECR must be offered in your region
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
- Verify all requirements above.
|
||||
- Get $REGION (e.g. `us-west-2`) credentials on your workstation. SSH into the host and run Docker manually with those creds. Does it work?
|
||||
- Verify kubelet is running with `--cloud-provider=aws`.
|
||||
- Check kubelet logs (e.g. `journalctl -t kubelet`) for log lines like:
|
||||
- `plugins.go:56] Registering credential provider: aws-ecr-key`
|
||||
- `provider.go:91] Refreshing cache for provider: *aws_credentials.ecrProvider`
|
||||
|
||||
### Using Azure Container Registry (ACR)
|
||||
When using [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/)
|
||||
you can authenticate using either an admin user or a service principal.
|
||||
In either case, authentication is done via standard Docker authentication. These instructions assume the
|
||||
[azure-cli](https://github.com/azure/azure-cli) command line tool.
|
||||
|
||||
You first need to create a registry and generate credentials, complete documentation for this can be found in
|
||||
the [Azure container registry documentation](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli).
|
||||
|
||||
Once you have created your container registry, you will use the following credentials to login:
|
||||
* `DOCKER_USER` : service principal, or admin username
|
||||
* `DOCKER_PASSWORD`: service principal password, or admin user password
|
||||
* `DOCKER_REGISTRY_SERVER`: `${some-registry-name}.azurecr.io`
|
||||
* `DOCKER_EMAIL`: `${some-email-address}`
|
||||
|
||||
Once you have those variables filled in you can [configure a Kubernetes Secret and use it to deploy a Pod]
|
||||
(/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
|
||||
|
||||
|
||||
### Configuring Nodes to Authenticate to a Private Repository
|
||||
|
||||
**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node
|
||||
with credentials for Google Container Registry. You cannot use this approach.
|
||||
|
||||
**Note:** if you are running on AWS EC2 and are using the EC2 Container Registry (ECR), the kubelet on each node will
|
||||
manage and update the ECR login credentials. You cannot use this approach.
|
||||
|
||||
**Note:** this approach is suitable if you can control node configuration. It
|
||||
will not work reliably on GCE, and any other cloud provider that does automatic
|
||||
node replacement.
|
||||
|
||||
Docker stores keys for private registries in the `$HOME/.dockercfg` or `$HOME/.docker/config.json` file. If you put this
|
||||
in the `$HOME` of user `root` on a kubelet, then docker will use it.
|
||||
|
||||
Here are the recommended steps to configuring your nodes to use a private registry. In this
|
||||
example, run these on your desktop/laptop:
|
||||
|
||||
1. Run `docker login [server]` for each set of credentials you want to use. This updates `$HOME/.docker/config.json`.
|
||||
1. View `$HOME/.docker/config.json` in an editor to ensure it contains just the credentials you want to use.
|
||||
1. Get a list of your nodes, for example:
|
||||
- if you want the names: `nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')`
|
||||
- if you want to get the IPs: `nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')`
|
||||
1. Copy your local `.docker/config.json` to the home directory of root on each node.
|
||||
- for example: `for n in $nodes; do scp ~/.docker/config.json root@$n:/root/.docker/config.json; done`
|
||||
|
||||
Verify by creating a pod that uses a private image, e.g.:
|
||||
|
||||
```yaml
|
||||
$ cat <<EOF > /tmp/private-image-test-1.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: private-image-test-1
|
||||
spec:
|
||||
containers:
|
||||
- name: uses-private-image
|
||||
image: $PRIVATE_IMAGE_NAME
|
||||
imagePullPolicy: Always
|
||||
command: [ "echo", "SUCCESS" ]
|
||||
EOF
|
||||
$ kubectl create -f /tmp/private-image-test-1.yaml
|
||||
pods/private-image-test-1
|
||||
$
|
||||
```
|
||||
|
||||
If everything is working, then, after a few moments, you should see:
|
||||
|
||||
```shell
|
||||
$ kubectl logs private-image-test-1
|
||||
SUCCESS
|
||||
```
|
||||
|
||||
If it failed, then you will see:
|
||||
|
||||
```shell
|
||||
$ kubectl describe pods/private-image-test-1 | grep "Failed"
|
||||
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
|
||||
```
|
||||
|
||||
|
||||
You must ensure all nodes in the cluster have the same `.docker/config.json`. Otherwise, pods will run on
|
||||
some nodes and fail to run on others. For example, if you use node autoscaling, then each instance
|
||||
template needs to include the `.docker/config.json` or mount a drive that contains it.
|
||||
|
||||
All pods will have read access to images in any private registry once private
|
||||
registry keys are added to the `.docker/config.json`.
|
||||
|
||||
**This was tested with a private docker repository as of 26 June with Kubernetes version v0.19.3.
|
||||
It should also work for a private registry such as quay.io, but that has not been tested.**
|
||||
|
||||
### Pre-pulling Images
|
||||
|
||||
**Note:** if you are running on Google Container Engine (GKE), there will already be a `.dockercfg` on each node
|
||||
with credentials for Google Container Registry. You cannot use this approach.
|
||||
|
||||
**Note:** this approach is suitable if you can control node configuration. It
|
||||
will not work reliably on GCE, and any other cloud provider that does automatic
|
||||
node replacement.
|
||||
|
||||
Be default, the kubelet will try to pull each image from the specified registry.
|
||||
However, if the `imagePullPolicy` property of the container is set to `IfNotPresent` or `Never`,
|
||||
then a local image is used (preferentially or exclusively, respectively).
|
||||
|
||||
If you want to rely on pre-pulled images as a substitute for registry authentication,
|
||||
you must ensure all nodes in the cluster have the same pre-pulled images.
|
||||
|
||||
This can be used to preload certain images for speed or as an alternative to authenticating to a private registry.
|
||||
|
||||
All pods will have read access to any pre-pulled images.
|
||||
|
||||
### Specifying ImagePullSecrets on a Pod
|
||||
|
||||
**Note:** This approach is currently the recommended approach for GKE, GCE, and any cloud-providers
|
||||
where node creation is automated.
|
||||
|
||||
Kubernetes supports specifying registry keys on a pod.
|
||||
|
||||
#### Creating a Secret with a Docker Config
|
||||
|
||||
Run the following command, substituting the appropriate uppercase values:
|
||||
|
||||
```shell
|
||||
$ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
|
||||
secret "myregistrykey" created.
|
||||
```
|
||||
|
||||
If you need access to multiple registries, you can create one secret for each registry.
|
||||
Kubelet will merge any `imagePullSecrets` into a single virtual `.docker/config.json`
|
||||
when pulling images for your Pods.
|
||||
|
||||
Pods can only reference image pull secrets in their own namespace,
|
||||
so this process needs to be done one time per namespace.
|
||||
|
||||
##### Bypassing kubectl create secrets
|
||||
|
||||
If for some reason you need multiple items in a single `.docker/config.json` or need
|
||||
control not given by the above command, then you can [create a secret using
|
||||
json or yaml](/docs/user-guide/secrets/#creating-a-secret-manually).
|
||||
|
||||
Be sure to:
|
||||
|
||||
- set the name of the data item to `.dockerconfigjson`
|
||||
- base64 encode the docker file and paste that string, unbroken
|
||||
as the value for field `data[".dockerconfigjson"]`
|
||||
- set `type` to `kubernetes.io/dockerconfigjson`
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: myregistrykey
|
||||
namespace: awesomeapps
|
||||
data:
|
||||
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
```
|
||||
|
||||
If you get the error message `error: no objects passed to create`, it may mean the base64 encoded string is invalid.
|
||||
If you get an error message like `Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...` it means
|
||||
the data was successfully un-base64 encoded, but could not be parsed as a `.docker/config.json` file.
|
||||
|
||||
#### Referring to an imagePullSecrets on a Pod
|
||||
|
||||
Now, you can create pods which reference that secret by adding an `imagePullSecrets`
|
||||
section to a pod definition.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: foo
|
||||
namespace: awesomeapps
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: janedoe/awesomeapp:v1
|
||||
imagePullSecrets:
|
||||
- name: myregistrykey
|
||||
```
|
||||
|
||||
This needs to be done for each pod that is using a private registry.
|
||||
|
||||
However, setting of this field can be automated by setting the imagePullSecrets
|
||||
in a [serviceAccount](/docs/user-guide/service-accounts) resource.
|
||||
|
||||
You can use this in conjunction with a per-node `.docker/config.json`. The credentials
|
||||
will be merged. This approach will work on Google Container Engine (GKE).
|
||||
|
||||
### Use Cases
|
||||
|
||||
There are a number of solutions for configuring private registries. Here are some
|
||||
common use cases and suggested solutions.
|
||||
|
||||
1. Cluster running only non-proprietary (e.g. open-source) images. No need to hide images.
|
||||
- Use public images on the Docker hub.
|
||||
- no configuration required
|
||||
- on GCE/GKE, a local mirror is automatically used for improved speed and availability
|
||||
1. Cluster running some proprietary images which should be hidden to those outside the company, but
|
||||
visible to all cluster users.
|
||||
- Use a hosted private [Docker registry](https://docs.docker.com/registry/)
|
||||
- may be hosted on the [Docker Hub](https://hub.docker.com/account/signup/), or elsewhere.
|
||||
- manually configure .docker/config.json on each node as described above
|
||||
- Or, run an internal private registry behind your firewall with open read access.
|
||||
- no Kubernetes configuration required
|
||||
- Or, when on GCE/GKE, use the project's Google Container Registry.
|
||||
- will work better with cluster autoscaling than manual node configuration
|
||||
- Or, on a cluster where changing the node configuration is inconvenient, use `imagePullSecrets`.
|
||||
1. Cluster with a proprietary images, a few of which require stricter access control
|
||||
- ensure [AlwaysPullImages admission controller](/docs/admin/admission-controllers/#alwayspullimages) is active, otherwise, all Pods potentially have access to all images
|
||||
- Move sensitive data into a "Secret" resource, instead of packaging it in an image.
|
||||
1. A multi-tenant cluster where each tenant needs own private registry
|
||||
- ensure [AlwaysPullImages admission controller](/docs/admin/admission-controllers/#alwayspullimages) is active, otherwise, all Pods of all tenants potentially have access to all images
|
||||
- run a private registry with authorization required.
|
||||
- generate registry credential for each tenant, put into secret, and populate secret to each tenant namespace.
|
||||
- tenant adds that secret to imagePullSecrets of each namespace.
|
||||
Reference in New Issue
Block a user